zoukankan      html  css  js  c++  java
  • Android 异步加载网络图片并缓存到本地

    在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片。

    软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下载图片,如果下载后就存到本地,下次读取时首先查看本地有没有,如果没有再从网络读取。

    记得2月份在和爱奇艺公司的项目总监一起搞联通的OTT盒子的时候他就提了一下软引用,奇艺做的手机客户端就是采用这种方法,所以你会发现奇艺客户端占用很大的空间,下面就分享一下异步加载网络图片的方法吧。

    FileCache.java

    import java.io.File;  
    import android.content.Context;  
     
    public class FileCache {  
     
       private File cacheDir;  
     
       public FileCache(Context context) {  
           // 找一个用来缓存图片的路径  
           if (android.os.Environment.getExternalStorageState().equals(  
                   android.os.Environment.MEDIA_MOUNTED))  
               cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),  
                       "文件夹名称");  
           else  
               cacheDir = context.getCacheDir();  
           if (!cacheDir.exists())  
               cacheDir.mkdirs();  
       }  
     
       public File getFile(String url) {  
           String filename = String.valueOf(url.hashCode());  
           File f = new File(cacheDir, filename);  
           return f;  
       }  
     
       public void clear() {  
           File[] files = cacheDir.listFiles();  
           if (files == null)  
               return;  
           for (File f : files)  
               f.delete();  
       }  
     
    }

    HttpUtil.java

    import java.io.ByteArrayOutputStream;  
    import java.io.File;  
    import java.io.FileNotFoundException;  
    import java.io.FileOutputStream;  
    import java.io.IOException;  
    import java.io.InputStream;  
    import java.io.OutputStream;  
    import java.io.UnsupportedEncodingException;  
    import java.net.HttpURLConnection;  
    import java.net.MalformedURLException;  
    import java.net.ProtocolException;  
    import java.net.URL;  
    import java.net.URLEncoder;  
    import java.util.Map;  
     
    /**
    * Http 请求工具类
    *  
    * @author Scorpio.Liu
    *  
    */  
    public class HttpUtil {  
     
       /**
        * 获取响应字符串
        *  
        * @param path
        *            路径
        * @param parameters
        *            参数
        * @return 响应字符串
        */  
       public static String getResponseStr(String path, Map<String, String> parameters) {  
           StringBuffer buffer = new StringBuffer();  
           URL url;  
           try {  
               if (parameters != null && !parameters.isEmpty()) {  
                   for (Map.Entry<String, String> entry : parameters.entrySet()) {  
                       // 完成转码操作  
                       buffer.append(entry.getKey()).append("=")  
                               .append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");  
                   }  
                   buffer.deleteCharAt(buffer.length() - 1);  
               }  
               url = new URL(path);  
               HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();  
               urlConnection.setConnectTimeout(3000);  
               urlConnection.setRequestMethod("POST");  
               urlConnection.setDoInput(true);// 表示从服务器获取数据  
               urlConnection.setDoOutput(true);// 表示向服务器写数据  
               // 获得上传信息的字节大小以及长度  
               byte[] mydata = buffer.toString().getBytes();  
               // 表示设置请求体的类型是文本类型  
               urlConnection.setRequestProperty("Content-Type",  
                       "application/x-www-form-urlencoded");  
               urlConnection.setRequestProperty("Content-Length", String.valueOf(mydata.length));  
               // 获得输出流,向服务器输出数据  
               OutputStream outputStream = urlConnection.getOutputStream();  
               outputStream.write(mydata, 0, mydata.length);  
               outputStream.close();  
               int responseCode = urlConnection.getResponseCode();  
               if (responseCode == 200) {  
                   return changeInputStream(urlConnection.getInputStream());  
               }  
           } catch (UnsupportedEncodingException e) {  
               e.printStackTrace();  
           } catch (MalformedURLException e) {  
               e.printStackTrace();  
           } catch (ProtocolException e) {  
               e.printStackTrace();  
           } catch (IOException e) {  
               e.printStackTrace();  
           }  
           return null;  
       }  
     
       private static String changeInputStream(InputStream inputStream) {  
           ByteArrayOutputStream outputStream = new ByteArrayOutputStream();  
           byte[] data = new byte[1024];  
           int len = 0;  
           String result = "";  
           if (inputStream != null) {  
               try {  
                   while ((len = inputStream.read(data)) != -1) {  
                       outputStream.write(data, 0, len);  
                   }  
                   result = new String(outputStream.toByteArray(), "UTF-8");  
               } catch (IOException e) {  
                   e.printStackTrace();  
               }  
           }  
           return result;  
       }  
     
       public static InputStream getInputStream(String path) {  
           URL url;  
           try {  
               url = new URL(path);  
               HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();  
               urlConnection.setConnectTimeout(3000);  
               urlConnection.setRequestMethod("GET");  
               urlConnection.setDoInput(true);// 表示从服务器获取数据  
               urlConnection.connect();  
               if (urlConnection.getResponseCode() == 200)  
                   return urlConnection.getInputStream();  
           } catch (MalformedURLException e) {  
               // TODO Auto-generated catch block  
               e.printStackTrace();  
           } catch (IOException e) {  
               // TODO Auto-generated catch block  
               e.printStackTrace();  
           } catch (Exception e) {  
               // TODO Auto-generated catch block  
               e.printStackTrace();  
           }  
           return null;  
       }  
     
       public static byte[] readStream(InputStream inStream) throws Exception {  
           ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  
           byte[] buffer = new byte[1024];  
           int len = -1;  
           while ((len = inStream.read(buffer)) != -1) {  
               outSteam.write(buffer, 0, len);  
     
           }  
           outSteam.close();  
           inStream.close();  
           return outSteam.toByteArray();  
       }  
     
       public static void CopyStream(String url, File f) {  
           FileOutputStream fileOutputStream = null;  
           InputStream inputStream = null;  
           try {  
               inputStream = getInputStream(url);  
               byte[] data = new byte[1024];  
               int len = 0;  
               fileOutputStream = new FileOutputStream(f);  
               while ((len = inputStream.read(data)) != -1) {  
                   fileOutputStream.write(data, 0, len);  
               }  
           } catch (FileNotFoundException e) {  
               e.printStackTrace();  
           } catch (IOException e) {  
               e.printStackTrace();  
           } finally {  
               if (inputStream != null) {  
                   try {  
                       inputStream.close();  
                   } catch (IOException e) {  
                       e.printStackTrace();  
                   }  
               }  
               if (fileOutputStream != null) {  
                   try {  
                       fileOutputStream.close();  
                   } catch (IOException e) {  
                       e.printStackTrace();  
                   }  
               }  
           }  
       }  
     
    }  

    MemoryCache.java

    import java.lang.ref.SoftReference;  
    import java.util.Collections;  
    import java.util.HashMap;  
    import java.util.Map;  
    import android.graphics.Bitmap;  
     
    public class MemoryCache {  
       private Map<String, SoftReference<Bitmap>> cache = Collections  
               .synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());// 软引用  
     
       public Bitmap get(String id) {  
           if (!cache.containsKey(id))  
               return null;  
           SoftReference<Bitmap> ref = cache.get(id);  
           return ref.get();  
       }  
     
       public void put(String id, Bitmap bitmap) {  
           cache.put(id, new SoftReference<Bitmap>(bitmap));  
       }  
     
       public void clear() {  
           cache.clear();  
       }  
    }

    ImageLoader.java

    import java.io.File;  
    import java.io.FileInputStream;  
    import java.io.FileNotFoundException;  
    import java.io.UnsupportedEncodingException;  
    import java.net.URLEncoder;  
    import java.util.Collections;  
    import java.util.Map;  
    import java.util.WeakHashMap;  
    import java.util.concurrent.ExecutorService;  
    import java.util.concurrent.Executors;  
    import android.app.Activity;  
    import android.content.Context;  
    import android.graphics.Bitmap;  
    import android.graphics.BitmapFactory;  
    import android.graphics.drawable.BitmapDrawable;  
    import android.widget.ImageView;  
     
    public class ImageLoader {  
     
       private MemoryCache memoryCache = new MemoryCache();  
       private FileCache fileCache;  
       private Map<ImageView, String> imageViews = Collections  
               .synchronizedMap(new WeakHashMap<ImageView, String>());  
       private ExecutorService executorService;  
       private boolean isSrc;  
     
       /**
        * @param context
        *            上下文对象
        * @param flag
        *            true为source资源,false为background资源
        */  
       public ImageLoader(Context context, boolean flag) {  
           fileCache = new FileCache(context);  
           executorService = Executors.newFixedThreadPool(5);  
           isSrc = flag;  
       }  
     
       final int stub_id = R.drawable.ic_launcher;  
     
       public void DisplayImage(String url, ImageView imageView) {  
           String u1 = url.substring(0, url.lastIndexOf("/") + 1);  
           String u2 = url.substring(url.lastIndexOf("/") + 1);  
           try {  
               u2 = URLEncoder.encode(u2, "UTF-8");  
           } catch (UnsupportedEncodingException e) {  
               e.printStackTrace();  
           }  
           url = u1 + u2;  
           imageViews.put(imageView, url);  
           Bitmap bitmap = memoryCache.get(url);  
           if (bitmap != null) {  
               if (isSrc)  
                   imageView.setImageBitmap(bitmap);  
               else  
                   imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));  
           } else {  
               queuePhoto(url, imageView);  
               if (isSrc)  
                   imageView.setImageResource(stub_id);  
               else  
                   imageView.setBackgroundResource(stub_id);  
           }  
       }  
     
       private void queuePhoto(String url, ImageView imageView) {  
           PhotoToLoad p = new PhotoToLoad(url, imageView);  
           executorService.submit(new PhotosLoader(p));  
       }  
     
       private Bitmap getBitmap(String url) {  
           try {  
               File f = fileCache.getFile(url);  
               // 从sd卡  
               Bitmap b = onDecodeFile(f);  
               if (b != null)  
                   return b;  
               // 从网络  
               Bitmap bitmap = null;  
               System.out.println("ImageLoader-->download");  
               HttpUtil.CopyStream(url, f);  
               bitmap = onDecodeFile(f);  
     
               return bitmap;  
           } catch (Exception ex) {  
               ex.printStackTrace();  
               return null;  
           }  
       }  
     
       public Bitmap onDecodeFile(File f) {  
           try {  
               return BitmapFactory.decodeStream(new FileInputStream(f));  
           } catch (FileNotFoundException e) {  
               // TODO Auto-generated catch block  
               e.printStackTrace();  
           }  
           return null;  
       }  
     
       /**
        * 解码图像用来减少内存消耗
        *  
        * @param f
        * @return
        */  
       public Bitmap decodeFile(File f) {  
           try {  
               // 解码图像大小  
               BitmapFactory.Options o = new BitmapFactory.Options();  
               o.inJustDecodeBounds = true;  
               BitmapFactory.decodeStream(new FileInputStream(f), null, o);  
               // 找到正确的刻度值,它应该是2的幂。  
               final int REQUIRED_SIZE = 70;  
               int width_tmp = o.outWidth, height_tmp = o.outHeight;  
               int scale = 1;  
               while (true) {  
                   if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)  
                       break;  
                   width_tmp /= 2;  
                   height_tmp /= 2;  
                   scale *= 2;  
               }  
               BitmapFactory.Options o2 = new BitmapFactory.Options();  
               o2.inSampleSize = scale;  
               return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);  
           } catch (FileNotFoundException e) {  
           }  
           return null;  
       }  
     
       /**
        * 任务队列
        *  
        * @author Scorpio.Liu
        *  
        */  
       private class PhotoToLoad {  
           public String url;  
           public ImageView imageView;  
     
           public PhotoToLoad(String u, ImageView i) {  
               url = u;  
               imageView = i;  
           }  
       }  
     
       class PhotosLoader implements Runnable {  
           PhotoToLoad photoToLoad;  
     
           PhotosLoader(PhotoToLoad photoToLoad) {  
               this.photoToLoad = photoToLoad;  
           }  
     
           @Override  
           public void run() {  
               if (imageViewReused(photoToLoad))  
                   return;  
               Bitmap bmp = getBitmap(photoToLoad.url);  
               memoryCache.put(photoToLoad.url, bmp);  
               if (imageViewReused(photoToLoad))  
                   return;  
               BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);  
               Activity a = (Activity) photoToLoad.imageView.getContext();  
               a.runOnUiThread(bd);  
           }  
       }  
     
       boolean imageViewReused(PhotoToLoad photoToLoad) {  
           String tag = imageViews.get(photoToLoad.imageView);  
           if (tag == null || !tag.equals(photoToLoad.url))  
               return true;  
           return false;  
       }  
     
       /**
        * 显示位图在UI线程
        *  
        * @author Scorpio.Liu
        *  
        */  
       class BitmapDisplayer implements Runnable {  
           Bitmap bitmap;  
           PhotoToLoad photoToLoad;  
     
           public BitmapDisplayer(Bitmap b, PhotoToLoad p) {  
               bitmap = b;  
               photoToLoad = p;  
           }  
     
           public void run() {  
               if (imageViewReused(photoToLoad))  
                   return;  
               if (bitmap != null) {  
                   if (isSrc)  
                       photoToLoad.imageView.setImageBitmap(bitmap);  
                   else  
                       photoToLoad.imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));  
               } else {  
                   if (isSrc)  
                       photoToLoad.imageView.setImageResource(stub_id);  
                   else  
                       photoToLoad.imageView.setBackgroundResource(stub_id);  
               }  
           }  
       }  
     
       public void clearCache() {  
           memoryCache.clear();  
           fileCache.clear();  
       }  
     
    }  

    使用的时候用ImageLoader这个类就ok了,很方便~

  • 相关阅读:
    != 比 & 的优先级高
    VC++ 报错:Heap corruption detected
    sqlite 查询数据库中所有的表名,判断某表是否存在,将某列所有数值去重后获得数量
    Unicode与UTF-8,UTF-16
    各种格式的压缩包解压,7zip 命令行
    bat批处理文件运行时隐藏cmd窗口
    标准库中 vector list等排序
    duilib 实现列表头任意拖动
    duilib 实现 XML重用(item完全重合的CList)
    C++-POJ2503-Babelfish[hash]
  • 原文地址:https://www.cnblogs.com/a354823200/p/4048561.html
Copyright © 2011-2022 走看看