现在的位置: 首页 > 移动开发 > 正文

android下载网络图片并缓存

2019年07月28日 移动开发 ⁄ 共 7147字 ⁄ 字号 评论关闭

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

异步加载类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{  
                        //下载失败,设置默认图片  
                    }  
                }  
            });  
        }  
          
    }  

抱歉!评论已关闭.