首页 > 代码库 > android下载网络图片并缓存

android下载网络图片并缓存

异步下载网络图片,并提供是否缓存至内存或外部文件的功能

异步加载类AsyncImageLoader

    public void downloadImage(final String url, final ImageCallback callback);

    public void downloadImage(final String url, final boolean cache2Memory, final ImageCallback callback);

    public void setCache2File(boolean flag);

    public void setCachedDir(String dir);

图片下载和缓存实现类LoaderImpl


1.AsyncImageLoader.java

[java] view plaincopy
  1. package com.imagecache;  
  2.   
  3. import java.lang.ref.SoftReference;  
  4. import java.util.HashMap;  
  5. import java.util.HashSet;  
  6. import java.util.Map;  
  7. import java.util.concurrent.ExecutorService;  
  8. import java.util.concurrent.Executors;  
  9.   
  10. import android.content.Context;  
  11. import android.graphics.Bitmap;  
  12. import android.os.Handler;  
  13. import android.util.Log;  
  14.   
  15. public class AsyncImageLoader {  
  16.     //保存正在下载的图片URL集合,避免重复下载用  
  17.     private static HashSet<String> sDownloadingSet;  
  18.     //软引用内存缓存  
  19.     private static Map<String,SoftReference<Bitmap>> sImageCache;   
  20.     //图片三种获取方式管理者,网络URL获取、内存缓存获取、外部文件缓存获取  
  21.     private static LoaderImpl impl;  
  22.     //线程池相关  
  23.     private static ExecutorService sExecutorService;  
  24.       
  25.     //通知UI线程图片获取ok时使用  
  26.     private Handler handler;   
  27.       
  28.       
  29.     /** 
  30.      * 异步加载图片完毕的回调接口 
  31.      */  
  32.     public interface ImageCallback{  
  33.         /** 
  34.          * 回调函数 
  35.          * @param bitmap: may be null! 
  36.          * @param imageUrl  
  37.          */  
  38.         public void onImageLoaded(Bitmap bitmap, String imageUrl);  
  39.     }  
  40.       
  41.     static{  
  42.         sDownloadingSet = new HashSet<String>();  
  43.         sImageCache = new HashMap<String,SoftReference<Bitmap>>();  
  44.         impl = new LoaderImpl(sImageCache);  
  45.     }  
  46.   
  47.     public AsyncImageLoader(Context context){  
  48.         handler = new Handler();  
  49.         startThreadPoolIfNecessary();  
  50.           
  51.         String defaultDir = context.getCacheDir().getAbsolutePath();  
  52.         setCachedDir(defaultDir);  
  53.     }  
  54.       
  55.     /** 
  56.      * 是否缓存图片至/data/data/package/cache/目录 
  57.      * 默认不缓存 
  58.      */  
  59.     public void setCache2File(boolean flag){  
  60.         impl.setCache2File(flag);  
  61.     }  
  62.       
  63.     /** 
  64.      * 设置缓存路径,setCache2File(true)时有效 
  65.      */  
  66.     public void setCachedDir(String dir){  
  67.         impl.setCachedDir(dir);  
  68.     }  
  69.   
  70.     /**开启线程池*/  
  71.     public static void startThreadPoolIfNecessary(){  
  72.         if(sExecutorService == null || sExecutorService.isShutdown() || sExecutorService.isTerminated()){  
  73.             sExecutorService = Executors.newFixedThreadPool(3);  
  74.             //sExecutorService = Executors.newSingleThreadExecutor();  
  75.         }  
  76.     }  
  77.       
  78.     /** 
  79.      * 异步下载图片,并缓存到memory中 
  80.      * @param url    
  81.      * @param callback  see ImageCallback interface 
  82.      */  
  83.     public void downloadImage(final String url, final ImageCallback callback){  
  84.         downloadImage(url, true, callback);  
  85.     }  
  86.       
  87.     /** 
  88.      *  
  89.      * @param url 
  90.      * @param cache2Memory 是否缓存至memory中 
  91.      * @param callback 
  92.      */  
  93.     public void downloadImage(final String url, final boolean cache2Memory, final ImageCallback callback){  
  94.         if(sDownloadingSet.contains(url)){  
  95.             Log.i("AsyncImageLoader", "###该图片正在下载,不能重复下载!");  
  96.             return;  
  97.         }  
  98.           
  99.         Bitmap bitmap = impl.getBitmapFromMemory(url);  
  100.         if(bitmap != null){  
  101.             if(callback != null){  
  102.                 callback.onImageLoaded(bitmap, url);  
  103.             }  
  104.         }else{  
  105.             //从网络端下载图片  
  106.             sDownloadingSet.add(url);  
  107.             sExecutorService.submit(new Runnable(){  
  108.                 @Override  
  109.                 public void run() {  
  110.                     final Bitmap bitmap = impl.getBitmapFromUrl(url, cache2Memory);  
  111.                     handler.post(new Runnable(){  
  112.                         @Override  
  113.                         public void run(){  
  114.                             if(callback != null)  
  115.                                 callback.onImageLoaded(bitmap, url);  
  116.                             sDownloadingSet.remove(url);  
  117.                         }  
  118.                     });  
  119.                 }  
  120.             });  
  121.         }  
  122.     }  
  123.       
  124.     /** 
  125.      * 预加载下一张图片,缓存至memory中 
  126.      * @param url  
  127.      */  
  128.     public void preLoadNextImage(final String url){  
  129.         //将callback置为空,只将bitmap缓存到memory即可。  
  130.         downloadImage(url, null);  
  131.     }  
  132.       
  133. }  


2.LoaderImpl.java

[java] view plaincopy
  1. package com.imagecache;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.lang.ref.SoftReference;  
  10. import java.net.HttpURLConnection;  
  11. import java.net.URL;  
  12. import java.security.MessageDigest;  
  13. import java.security.NoSuchAlgorithmException;  
  14. import java.util.Map;  
  15.   
  16. import android.graphics.Bitmap;  
  17. import android.graphics.BitmapFactory;  
  18.   
  19. /** 
  20.  *  
  21.  * @author Administrator 
  22.  * @desc 异步加载图片管理器 
  23.  * 
  24.  */  
  25. public class LoaderImpl {  
  26.     //内存中的软应用缓存  
  27.     private Map<String, SoftReference<Bitmap>> imageCache;  
  28.       
  29.     //是否缓存图片至本地文件  
  30.     private boolean cache2FileFlag = false;  
  31.       
  32.     //缓存目录,默认是/data/data/package/cache/目录  
  33.     private String cachedDir;  
  34.       
  35.     public LoaderImpl(Map<String, SoftReference<Bitmap>> imageCache){  
  36.         this.imageCache = imageCache;  
  37.     }  
  38.       
  39.     /** 
  40.      * 是否缓存图片至外部文件 
  41.      * @param flag  
  42.      */  
  43.     public void setCache2File(boolean flag){  
  44.         cache2FileFlag = flag;  
  45.     }  
  46.       
  47.     /** 
  48.      * 设置缓存图片到外部文件的路径 
  49.      * @param cacheDir 
  50.      */  
  51.     public void setCachedDir(String cacheDir){  
  52.         this.cachedDir = cacheDir;  
  53.     }  
  54.       
  55.     /** 
  56.      * 从网络端下载图片 
  57.      * @param url 网络图片的URL地址 
  58.      * @param cache2Memory 是否缓存(缓存在内存中) 
  59.      * @return bitmap 图片bitmap结构 
  60.      *  
  61.      */  
  62.     public Bitmap getBitmapFromUrl(String url, boolean cache2Memory){  
  63.         Bitmap bitmap = null;  
  64.         try{  
  65.             URL u = new URL(url);  
  66.             HttpURLConnection conn = (HttpURLConnection)u.openConnection();    
  67.             InputStream is = conn.getInputStream();  
  68.             bitmap = BitmapFactory.decodeStream(is);  
  69.               
  70.             if(cache2Memory){  
  71.                 //1.缓存bitmap至内存软引用中  
  72.                 imageCache.put(url, new SoftReference<Bitmap>(bitmap));  
  73.                 if(cache2FileFlag){  
  74.                     //2.缓存bitmap至/data/data/packageName/cache/文件夹中  
  75.                     String fileName = getMD5Str(url);  
  76.                     String filePath = this.cachedDir + "/" +fileName;  
  77.                     FileOutputStream fos = new FileOutputStream(filePath);  
  78.                     bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);  
  79.                 }  
  80.             }  
  81.               
  82.             is.close();  
  83.             conn.disconnect();  
  84.             return bitmap;  
  85.         }catch(IOException e){  
  86.             e.printStackTrace();  
  87.             return null;  
  88.         }  
  89.     }  
  90.       
  91.     /** 
  92.      * 从内存缓存中获取bitmap 
  93.      * @param url 
  94.      * @return bitmap or null. 
  95.      */  
  96.     public Bitmap getBitmapFromMemory(String url){  
  97.         Bitmap bitmap = null;  
  98.         if(imageCache.containsKey(url)){  
  99.             synchronized(imageCache){  
  100.                 SoftReference<Bitmap> bitmapRef = imageCache.get(url);  
  101.                 if(bitmapRef != null){  
  102.                     bitmap = bitmapRef.get();  
  103.                     return bitmap;  
  104.                 }  
  105.             }  
  106.         }  
  107.         //从外部缓存文件读取  
  108.         if(cache2FileFlag){  
  109.             bitmap = getBitmapFromFile(url);  
  110.             if(bitmap != null)  
  111.                 imageCache.put(url, new SoftReference<Bitmap>(bitmap));  
  112.         }  
  113.           
  114.         return bitmap;  
  115.     }  
  116.       
  117.     /** 
  118.      * 从外部文件缓存中获取bitmap 
  119.      * @param url 
  120.      * @return 
  121.      */  
  122.     private Bitmap getBitmapFromFile(String url){  
  123.         Bitmap bitmap = null;  
  124.         String fileName = getMD5Str(url);  
  125.         if(fileName == null)  
  126.             return null;  
  127.           
  128.         String filePath = cachedDir + "/" + fileName;  
  129.           
  130.         try {  
  131.             FileInputStream fis = new FileInputStream(filePath);  
  132.             bitmap = BitmapFactory.decodeStream(fis);  
  133.         } catch (FileNotFoundException e) {  
  134.             e.printStackTrace();  
  135.             bitmap = null;  
  136.         }  
  137.         return bitmap;  
  138.     }  
  139.       
  140.       
  141.     /**   
  142.      * MD5 加密   
  143.      */     
  144.     private static String getMD5Str(String str) {     
  145.         MessageDigest messageDigest = null;     
  146.         try {     
  147.             messageDigest = MessageDigest.getInstance("MD5");     
  148.             messageDigest.reset();     
  149.             messageDigest.update(str.getBytes("UTF-8"));     
  150.         } catch (NoSuchAlgorithmException e) {     
  151.             System.out.println("NoSuchAlgorithmException caught!");     
  152.             return null;  
  153.         } catch (UnsupportedEncodingException e) {     
  154.             e.printStackTrace();  
  155.             return null;  
  156.         }     
  157.      
  158.         byte[] byteArray = messageDigest.digest();     
  159.         StringBuffer md5StrBuff = new StringBuffer();     
  160.         for (int i = 0; i < byteArray.length; i++) {                 
  161.             if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)     
  162.                 md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));     
  163.             else     
  164.                 md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));     
  165.         }     
  166.      
  167.         return md5StrBuff.toString();     
  168.     }    
  169.   
  170.     /**   
  171.      * MD5 加密   
  172.     private static String getMD5Str(Object...objects){ 
  173.         StringBuilder stringBuilder=new StringBuilder(); 
  174.         for (Object object : objects) { 
  175.             stringBuilder.append(object.toString()); 
  176.         } 
  177.         return getMD5Str(stringBuilder.toString()); 
  178.     }*/   
  179. }  


3.测试Activity

[java] view plaincopy
    1. package com.imagecache;  
    2.   
    3. import android.app.Activity;  
    4. import android.graphics.Bitmap;  
    5. import android.os.Bundle;  
    6. import android.widget.ImageView;  
    7.   
    8. public class MainActivity extends Activity {  
    9.     /** Called when the activity is first created. */  
    10.     @Override  
    11.     public void onCreate(Bundle savedInstanceState) {  
    12.         super.onCreate(savedInstanceState);  
    13.         setContentView(R.layout.main);  
    14.           
    15.         final ImageView iv = (ImageView)findViewById(R.id.iv);  
    16.         //网络图片地址  
    17.         String imgUrl = "http://...";  
    18.           
    19.         //for test  
    20.         AsyncImageLoader loader = new AsyncImageLoader(getApplicationContext());  
    21.           
    22.         //将图片缓存至外部文件中  
    23.         loader.setCache2File(true); //false  
    24.         //设置外部缓存文件夹  
    25.         loader.setCachedDir(this.getCacheDir().getAbsolutePath());  
    26.           
    27.         //下载图片,第二个参数是否缓存至内存中  
    28.         loader.downloadImage(imgUrl, true/*false*/, new AsyncImageLoader.ImageCallback() {  
    29.             @Override  
    30.             public void onImageLoaded(Bitmap bitmap, String imageUrl) {  
    31.                 if(bitmap != null){  
    32.                     iv.setImageBitmap(bitmap);  
    33.                 }else{  
    34.                     //下载失败,设置默认图片  
    35.                 }  
    36.             }  
    37.         });  
    38.     }  
    39.       
转自:http://blog.csdn.net/liliang497/article/details/7221110