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

  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

  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

 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     
40 }

 

posted @ 2014-07-15 11:28  公孙 轩辕  阅读(433)  评论(0编辑  收藏  举报