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

package com.imagecache;  
  
import java.lang.ref.SoftReference;  
import java.util.HashMap;  
import java.util.HashSet;  
import java.util.Map;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
  
import android.content.Context;  
import android.graphics.Bitmap;  
import android.os.Handler;  
import android.util.Log;  
  
public class AsyncImageLoader {  
    //保存正在下载的图片URL集合,避免重复下载用  
    private static HashSet<String> sDownloadingSet;  
    //软引用内存缓存  
    private static Map<String,SoftReference<Bitmap>> sImageCache;   
    //图片三种获取方式管理者,网络URL获取、内存缓存获取、外部文件缓存获取  
    private static LoaderImpl impl;  
    //线程池相关  
    private static ExecutorService sExecutorService;  
      
    //通知UI线程图片获取ok时使用  
    private Handler handler;   
      
      
    /** 
     * 异步加载图片完毕的回调接口 
     */  
    public interface ImageCallback{  
        /** 
         * 回调函数 
         * @param bitmap: may be null! 
         * @param imageUrl  
         */  
        public void onImageLoaded(Bitmap bitmap, String imageUrl);  
    }  
      
    static{  
        sDownloadingSet = new HashSet<String>();  
        sImageCache = new HashMap<String,SoftReference<Bitmap>>();  
        impl = new LoaderImpl(sImageCache);  
    }  
  
    public AsyncImageLoader(Context context){  
        handler = new Handler();  
        startThreadPoolIfNecessary();  
          
        String defaultDir = context.getCacheDir().getAbsolutePath();  
        setCachedDir(defaultDir);  
    }  
      
    /** 
     * 是否缓存图片至/data/data/package/cache/目录 
     * 默认不缓存 
     */  
    public void setCache2File(boolean flag){  
        impl.setCache2File(flag);  
    }  
      
    /** 
     * 设置缓存路径,setCache2File(true)时有效 
     */  
    public void setCachedDir(String dir){  
        impl.setCachedDir(dir);  
    }  
  
    /**开启线程池*/  
    public static void startThreadPoolIfNecessary(){  
        if(sExecutorService == null || sExecutorService.isShutdown() || sExecutorService.isTerminated()){  
            sExecutorService = Executors.newFixedThreadPool(3);  
            //sExecutorService = Executors.newSingleThreadExecutor();  
        }  
    }  
      
    /** 
     * 异步下载图片,并缓存到memory中 
     * @param url    
     * @param callback  see ImageCallback interface 
     */  
    public void downloadImage(final String url, final ImageCallback callback){  
        downloadImage(url, true, callback);  
    }  
      
    /** 
     *  
     * @param url 
     * @param cache2Memory 是否缓存至memory中 
     * @param callback 
     */  
    public void downloadImage(final String url, final boolean cache2Memory, final ImageCallback callback){  
        if(sDownloadingSet.contains(url)){  
            Log.i("AsyncImageLoader", "###该图片正在下载,不能重复下载!");  
            return;  
        }  
          
        Bitmap bitmap = impl.getBitmapFromMemory(url);  
        if(bitmap != null){  
            if(callback != null){  
                callback.onImageLoaded(bitmap, url);  
            }  
        }else{  
            //从网络端下载图片  
            sDownloadingSet.add(url);  
            sExecutorService.submit(new Runnable(){  
                @Override  
                public void run() {  
                    final Bitmap bitmap = impl.getBitmapFromUrl(url, cache2Memory);  
                    handler.post(new Runnable(){  
                        @Override  
                        public void run(){  
                            if(callback != null)  
                                callback.onImageLoaded(bitmap, url);  
                            sDownloadingSet.remove(url);  
                        }  
                    });  
                }  
            });  
        }  
    }  
      
    /** 
     * 预加载下一张图片,缓存至memory中 
     * @param url  
     */  
    public void preLoadNextImage(final String url){  
        //将callback置为空,只将bitmap缓存到memory即可。  
        downloadImage(url, null);  
    }  
      
}  

2.LoaderImpl.java

package com.imagecache;  
  
import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.UnsupportedEncodingException;  
import java.lang.ref.SoftReference;  
import java.net.HttpURLConnection;  
import java.net.URL;  
import java.security.MessageDigest;  
import java.security.NoSuchAlgorithmException;  
import java.util.Map;  
  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
  
/** 
 *  
 * @author Administrator 
 * @desc 异步加载图片管理器 
 * 
 */  
public class LoaderImpl {  
    //内存中的软应用缓存  
    private Map<String, SoftReference<Bitmap>> imageCache;  
      
    //是否缓存图片至本地文件  
    private boolean cache2FileFlag = false;  
      
    //缓存目录,默认是/data/data/package/cache/目录  
    private String cachedDir;  
      
    public LoaderImpl(Map<String, SoftReference<Bitmap>> imageCache){  
        this.imageCache = imageCache;  
    }  
      
    /** 
     * 是否缓存图片至外部文件 
     * @param flag  
     */  
    public void setCache2File(boolean flag){  
        cache2FileFlag = flag;  
    }  
      
    /** 
     * 设置缓存图片到外部文件的路径 
     * @param cacheDir 
     */  
    public void setCachedDir(String cacheDir){  
        this.cachedDir = cacheDir;  
    }  
      
    /** 
     * 从网络端下载图片 
     * @param url 网络图片的URL地址 
     * @param cache2Memory 是否缓存(缓存在内存中) 
     * @return bitmap 图片bitmap结构 
     *  
     */  
    public Bitmap getBitmapFromUrl(String url, boolean cache2Memory){  
        Bitmap bitmap = null;  
        try{  
            URL u = new URL(url);  
            HttpURLConnection conn = (HttpURLConnection)u.openConnection();    
            InputStream is = conn.getInputStream();  
            bitmap = BitmapFactory.decodeStream(is);  
              
            if(cache2Memory){  
                //1.缓存bitmap至内存软引用中  
                imageCache.put(url, new SoftReference<Bitmap>(bitmap));  
                if(cache2FileFlag){  
                    //2.缓存bitmap至/data/data/packageName/cache/文件夹中  
                    String fileName = getMD5Str(url);  
                    String filePath = this.cachedDir + "/" +fileName;  
                    FileOutputStream fos = new FileOutputStream(filePath);  
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);  
                }  
            }  
              
            is.close();  
            conn.disconnect();  
            return bitmap;  
        }catch(IOException e){  
            e.printStackTrace();  
            return null;  
        }  
    }  
      
    /** 
     * 从内存缓存中获取bitmap 
     * @param url 
     * @return bitmap or null. 
     */  
    public Bitmap getBitmapFromMemory(String url){  
        Bitmap bitmap = null;  
        if(imageCache.containsKey(url)){  
            synchronized(imageCache){  
                SoftReference<Bitmap> bitmapRef = imageCache.get(url);  
                if(bitmapRef != null){  
                    bitmap = bitmapRef.get();  
                    return bitmap;  
                }  
            }  
        }  
        //从外部缓存文件读取  
        if(cache2FileFlag){  
            bitmap = getBitmapFromFile(url);  
            if(bitmap != null)  
                imageCache.put(url, new SoftReference<Bitmap>(bitmap));  
        }  
          
        return bitmap;  
    }  
      
    /** 
     * 从外部文件缓存中获取bitmap 
     * @param url 
     * @return 
     */  
    private Bitmap getBitmapFromFile(String url){  
        Bitmap bitmap = null;  
        String fileName = getMD5Str(url);  
        if(fileName == null)  
            return null;  
          
        String filePath = cachedDir + "/" + fileName;  
          
        try {  
            FileInputStream fis = new FileInputStream(filePath);  
            bitmap = BitmapFactory.decodeStream(fis);  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
            bitmap = null;  
        }  
        return bitmap;  
    }  
      
      
    /**   
     * MD5 加密   
     */     
    private static String getMD5Str(String str) {     
        MessageDigest messageDigest = null;     
        try {     
            messageDigest = MessageDigest.getInstance("MD5");     
            messageDigest.reset();     
            messageDigest.update(str.getBytes("UTF-8"));     
        } catch (NoSuchAlgorithmException e) {     
            System.out.println("NoSuchAlgorithmException caught!");     
            return null;  
        } catch (UnsupportedEncodingException e) {     
            e.printStackTrace();  
            return null;  
        }     
     
        byte[] byteArray = messageDigest.digest();     
        StringBuffer md5StrBuff = new StringBuffer();     
        for (int i = 0; i < byteArray.length; i++) {                 
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)     
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));     
            else     
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));     
        }     
     
        return md5StrBuff.toString();     
    }    
  
    /**   
     * MD5 加密   
    private static String getMD5Str(Object...objects){ 
        StringBuilder stringBuilder=new StringBuilder(); 
        for (Object object : objects) { 
            stringBuilder.append(object.toString()); 
        } 
        return getMD5Str(stringBuilder.toString()); 
    }*/   
}  

3.测试Activity

package com.imagecache;  
  
import android.app.Activity;  
import android.graphics.Bitmap;  
import android.os.Bundle;  
import android.widget.ImageView;  
  
public class MainActivity extends Activity {  
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        final ImageView iv = (ImageView)findViewById(R.id.iv);  
        //网络图片地址  
        String imgUrl = "http://...";  
          
        //for test  
        AsyncImageLoader loader = new AsyncImageLoader(getApplicationContext());  
          
        //将图片缓存至外部文件中  
        loader.setCache2File(true); //false  
        //设置外部缓存文件夹  
        loader.setCachedDir(this.getCacheDir().getAbsolutePath());  
          
        //下载图片,第二个参数是否缓存至内存中  
        loader.downloadImage(imgUrl, true/*false*/, new AsyncImageLoader.ImageCallback() {  
            @Override  
            public void onImageLoaded(Bitmap bitmap, String imageUrl) {  
                if(bitmap != null){  
                    iv.setImageBitmap(bitmap);  
                }else{  
                    //下载失败,设置默认图片  
                }  
            }  
        });  
    }  
      
}  
原文地址:https://www.cnblogs.com/zhujiabin/p/6866050.html