异步图片下载引擎(升级版——ExecutorService+handler)

[Android分享] 异步图片下载引擎(升级版——ExecutorService+handler) 

  [复制链接]
   

13

主题

5

好友

844

积分

No.4 中级开发者

Rank: 4

升级  24%

精华
0
帖子
198
e币
997 元
跳转到指定楼层
楼主
 
 发表于 2013-4-7 14:39:10 |只看该作者 |正序浏览
以前发过一篇有关加载图片的文章,是处理应用中常常遇到的加载列表缩略图与大图的文章,当时是因为赶项目,时间仓促,并没有过多的考虑,闲暇时间,反思了一下,觉得以前所用的方法过于笨拙且消耗手机资源加大,思量再三,又重新做了一个
此次引用了线程池ExecutorService与改用了Handler的post方法

采用线程池的目的:
1、大幅减少开启线程的数量,重复利用有限的线程
2、减少手机的资源损耗

采用Handler的Post方法的目的:
1、是为了更加规范的调用API
2、是图片的呈现更加可靠


             <ignore_js_op>device-2013-04-07-143747.png 

不多说了!

-------------------------------------------------------------------------------------------------------------------------------
java代码

图片加载管理类AsynDownloadManager,需要从外部传入UI线程的Handler


public class AsynDownloadManager {
        private static String ThumbFolder = "Temp/Thumb";//缩略图文件夹
        private static String ImageFolder="Temp/Image";//大图文件夹
        
        private static Handler handler;//UI handler
        private static ExecutorService pool;//线程池
        private static Map<String, SoftReference<Bitmap>> cacheImage;//软引用
        private int ThreadCount=5;//默认线程池可用线程数
        
          /**
           * 创建目录
           */
        static {
                if (isSDCardAvailable()) {
                        File file = new File(Environment.getExternalStorageDirectory(),ThumbFolder);
                        if (!file.exists()) {
                                file.mkdirs();
                        }
                        File file1 = new File(Environment.getExternalStorageDirectory(),ImageFolder);
                        if (!file1.exists()) {
                                file1.mkdirs();
                        }
                }
        }
        
        public AsynDownloadManager() {
                cacheImage = new HashMap<String, SoftReference<Bitmap>>();
                pool = Executors.newFixedThreadPool(ThreadCount);
        }
        
        static AsynDownloadManager manager=null;
        
        
        
        //**********************************************************************************供外部调用的主方法
        /**
         * 获取加载器
         * @return AsynDownloadManager
         */
        public static AsynDownloadManager getInterface(){
                if(manager==null){
                        manager=new AsynDownloadManager();
                }
                return manager;
        }
        /**
         * 加载图片(缩略图)
         * @param url
         * @param imageView
         */
        public static void loadThembBitmap(final String url, final ImageView imageView) {
                pool.submit(new Runnable() {
                        public void run() {
                                //首先从SoftReference中获取
                                Bitmap bitmapTemp=getFromSoftReference(url);
                                if(bitmapTemp==null){
                               //从SDcard中获取                
                                         bitmapTemp=getFromSDcard(url, ThumbFolder,false);
                                         if(bitmapTemp==null){
                                                 //从URL获取
                                                 bitmapTemp=getFromURL(url, ThumbFolder,false);
                                         }
                                }
                                final Bitmap bitmap=bitmapTemp;
                                handler.post(new Runnable() {//发送到Handler队列,依次显示
                                        public void run() {
                                                imageView.setImageBitmap(bitmap);
                                        }
                                });
                        }
                });
        }
        
        /**
         * 加载图片(大图)
         * @param url
         * @param imageView
         * @param isZip 是否压缩
         */
        public static void  loadBitmap(final String url, final ImageView imageView,final boolean isZip){
                pool.submit(new Runnable() {
                        public void run() {
                                //因为单图较大,不用SoftReference
                                
                                Bitmap bitmapTemp=null;
                               //从SDcard中获取                
                                         bitmapTemp=getFromSDcard(url, ImageFolder,isZip);
                                         if(bitmapTemp==null){
                                                 //从URL获取
                                                 bitmapTemp=getFromURL(url, ImageFolder,isZip);
                                         }
                                final Bitmap bitmap=bitmapTemp;
                                handler.post(new Runnable() {//发送到Handler队列,依次显示
                                        public void run() {
                                                imageView.setImageBitmap(bitmap);
                                        }
                                });
                        }
                });
        }
        //**********************************************************************************
        
        
        
        
        
          
          
         /**
          * 从缓存中获取
          * @param url
          * @param bitmap
          * @return Bitmap
          */
          public static Bitmap getFromSoftReference(String url){                  
                  if(!cacheImage.containsKey(url)){
                          return null;
                  }else{
                          return cacheImage.get(url).get();
                  }
          }
          
          /**
           * 从SDcard获取(下载并返回)
           * @param imageUrl
           * @param folderPath
           * @return Bitmap
           */
          public static Bitmap getFromURL(String imageUrl, String folderPath,boolean isZip){
                        URL mUrl;
                        InputStream is = null;
                        Bitmap bitmap = null; 
                        try {
                                mUrl = new URL(imageUrl);
                                is = (InputStream) mUrl.getContent();
                                if(isSDCardAvailable()){
                                        String fileName = imageUrl.substring(imageUrl.lastIndexOf('/')+1);
                                        File basePathFile = new File(Environment.getExternalStorageDirectory(), folderPath);
                                        File file = new File(basePathFile, fileName+".tmp");
                                        if(!file.exists()){
                                                file.createNewFile();
                                        }
                                        FileOutputStream outputStream = new FileOutputStream(file);
                                        byte[] b = new byte[512];
                                        int offset;
                                        while((offset=is.read(b))!=-1){
                                                outputStream.write(b, 0, offset);
                                        }
                                        outputStream.flush();
                                        outputStream.close();
                                        is.close();
                                        basePathFile = new File(basePathFile, fileName);
                                        if(basePathFile.exists()){
                                                basePathFile.delete();
                                        }
                                        if(file.renameTo(basePathFile)){
                                                is = new FileInputStream(basePathFile);
                                        }
                                        // 读取图片
                                        bitmap=getBitmap(basePathFile.getAbsolutePath(), isZip);
                                        
                                        if(isZip==false){
                                                 //缩略图加入到软引用
                                                  SoftReference<Bitmap> softReference=new SoftReference<Bitmap>(bitmap);
                                                  cacheImage.put(imageUrl, softReference);
                                        }
                                         
                                }
                        } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                        }

                        return bitmap;
                }
          
          /**
           * 从SDcard获取
           * @param url
           * @param folderPath
           * @return Bitmap
           */
          public static Bitmap getFromSDcard(String url,String folderPath,boolean isZip){
                  Bitmap bitmap = null;
                  String fileName = url.substring(url.lastIndexOf('/')+1);
                  File basePathFile = new File(Environment.getExternalStorageDirectory(), folderPath);
                  basePathFile = new File(basePathFile, fileName);
                  if(basePathFile.exists()){
                          bitmap=getBitmap(basePathFile.getAbsolutePath(), isZip);
                  }                  
                  return bitmap;
          }
        /**
         * 检查SDCard是否可用
         * 
         * @return
         */
        public static final boolean isSDCardAvailable() {
                return Environment.getExternalStorageState().equals(
                                Environment.MEDIA_MOUNTED);
        }

        //---------------------------------------------------------------------------------
        
         /**
     * 读取SDcard中的图片资源(解决内存溢出问题)
     * @param pathName 文件路径名
     * @param isZip  是否降低采样率
     * @return Bitmap
     */
        public static Bitmap getBitmap(String pathName,boolean isZip){
                Bitmap bitmap=null;
                if(isZip==true){
                        BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
            bitmap=BitmapFactory.decodeFile(pathName, options);
                }else{
                         bitmap=BitmapFactory.decodeFile(pathName);
                }
                return  bitmap;
        }

        //---------------------------------------------------------------便于外部修改参数
        public static String getThumbFolder() {
                return ThumbFolder;
        }

        public static void setThumbFolder(String thumbFolder) {
                ThumbFolder = thumbFolder;
        }

        public static String getImageFolder() {
                return ImageFolder;
        }

        public static void setImageFolder(String imageFolder) {
                ImageFolder = imageFolder;
        }

        public int getThreadCount() {
                return ThreadCount;
        }

        public void setThreadCount(int threadCount) {
                ThreadCount = threadCount;
        }

        public Handler getHandler() {
                return handler;
        }

        public void setHandler(Handler handler) {
                this.handler = handler;
        }
        

        
}



------------------------------------------------------------------------------------------------------------------------------
调用示例

一、对于缩略图:
1、在Activity中实例化AsynDownloadManager:
        Handler handler=new Handler();
  

2、对于ListView或GridView中的缩略图,一般可在自定义Adapter的的构造中:
        AsynDownloadManager manager=AsynDownloadManager.getInterface();
        manager.setHandler(handler);

    getView()方法中作如下调用:
       manager.loadThembBitmap(urlList.get(position), imageView);

3、OK

二、对于大图:(压缩)

     前两步同上

     3、 直接调用
     AsynDownloadManager.getInterface().loadBitmap(url, ImageView, true);        
     当然最后那个参数也可以用false,即不压缩的模式

---------------------------------------------------------------------------------------------------------------------------------

OK!
posted @ 2013-07-10 09:58  wanqi  阅读(839)  评论(0编辑  收藏  举报