Android 多线程网络下载图片

来源:互联网 发布:ubuntu 14.04 32位iso 编辑:程序博客网 时间:2024/05/17 17:59

   最近项目中碰到了多线程下载图片的问题,我自己写了一个工具类 ImageLoader, 该工具类支持图片缓存:有SDCARD缓存,内存缓存等,支持多线程下载,其具体实现思路为:

 1、实现一个线程池 ExecutorService,将下载多线程的任务添加到该线程池中,可以定义线程池的大小

  2、下载到图片成功之后,如何通知UI线程去更新UI

 3、图片的缓存处理等。

其核心代码如下:

 

import java.io.File;import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;  import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory;import android.text.TextUtils;import android.widget.ImageView;import com.giant.lib.utils.GiantLog;import giant.activity.R;public class ImageLoader {    final int stub_id = R.drawable.default_user_ico;    MemoryCache memoryCache = new MemoryCache();    FileCache fileCache;     private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());    ExecutorService executorService;    private static final String TAG = "ImageLoader";      public ImageLoader(Context context){         fileCache = new FileCache(context);        executorService = Executors.newFixedThreadPool(5);    }     /**     * 显示图片需要默认图片     * @param url     * @param imageView     */    public void DisplayImage(String url, ImageView imageView)    {         imageViews.put(imageView, url);        Bitmap bitmap = memoryCache.get(url);        if(TextUtils.isEmpty(url)){            imageView.setImageResource(R.drawable.default_user_ico);        }//        Bitmap bitmap = null;        if(bitmap!= null)   { //先加载内存中的缓存            imageView.setImageBitmap(bitmap);            GiantLog.d(TAG, "load image data form memory");        }        else        {             queuePhoto(url,imageView);            imageView.setImageResource(stub_id);         }     }    /**     * 显示图片不需要默认图片     * @param url     * @param imageView     */    public void DisplayImageWithNodefault(String url, ImageView imageView)    {        imageViews.put(imageView, url);        Bitmap bitmap = memoryCache.get(url);//        Bitmap bitmap = null;        if(bitmap!= null)   { //先加载内存中的缓存            imageView.setImageBitmap(bitmap);            GiantLog.d(TAG, "load image data form memory");        }        else        {            queuePhoto(url,imageView);           // imageView.setImageResource(stub_id);        }    }    private void queuePhoto(String url, ImageView imageView)    {         PhotoToLoad p = new PhotoToLoad(url,imageView);        executorService.submit(new PhotosLoader(p));     }       private Bitmap getBitmap(String url)    {         File f = fileCache.getFile(url);        //从sd卡        Bitmap b = decodeFile(f);        if(b!=null)  {            GiantLog.d(TAG,"load image from sdcard");            return b;        }        //从网络        try {             Bitmap bitmap = null;            URL imageUrl = new URL(url);             HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();             conn.setConnectTimeout(30000);             conn.setReadTimeout(30000);             conn.setInstanceFollowRedirects(true);             InputStream is = conn.getInputStream();            OutputStream os = new FileOutputStream(f);             Utils.CopyStream(is, os);             os.close();             bitmap = decodeFile(f);            GiantLog.d(TAG,"load image from network" );            return bitmap;         } catch (Exception ex){            ex.printStackTrace();            return null;         }     }      //解码图像用来减少内存消耗    private Bitmap decodeFile(File f){         try {             //解码图像大小            BitmapFactory.Options o = new BitmapFactory.Options();             o.inJustDecodeBounds = true;             BitmapFactory.decodeStream(new FileInputStream(f),null,o);               //找到正确的刻度值,它应该是2的幂。            final int REQUIRED_SIZE = 70;            int width_tmp = o.outWidth, height_tmp = o.outHeight;            int scale = 1;            while(true){                 if(width_tmp/2 < REQUIRED_SIZE || height_tmp/2 < REQUIRED_SIZE)                    break;                 width_tmp/=2;                 height_tmp/=2;                 scale*=2;             }               BitmapFactory.Options options = new BitmapFactory.Options();            options.inSampleSize = 1;            return BitmapFactory.decodeStream(new FileInputStream(f), null, options);        } catch (FileNotFoundException e) {            GiantLog.d(TAG,"exception:" + e);        }        return null;     }       private class PhotoToLoad     {         public String url;        public ImageView imageView;        public PhotoToLoad(String u, ImageView i){            url = u;            imageView=i;        }    }     class PhotosLoader implements Runnable {         PhotoToLoad photoToLoad;         PhotosLoader(PhotoToLoad photoToLoad){             this.photoToLoad=photoToLoad;         }           @Override        public void run() {             if(imageViewReused(photoToLoad))                 return;             Bitmap bmp = getBitmap(photoToLoad.url);            memoryCache.put(photoToLoad.url, bmp);             if(imageViewReused(photoToLoad))                 return;             BitmapDisplayer bitmapDisplayer = new BitmapDisplayer(bmp, photoToLoad);            Activity activity =(Activity)photoToLoad.imageView.getContext();            activity.runOnUiThread(bitmapDisplayer);        }     }     boolean imageViewReused(PhotoToLoad photoToLoad){         String tag = imageViews.get(photoToLoad.imageView);        return tag == null || !tag.equals(photoToLoad.url);    }      //用于显示位图在UI线程    class BitmapDisplayer implements Runnable     {         Bitmap bitmap;         PhotoToLoad photoToLoad;         public BitmapDisplayer(Bitmap b, PhotoToLoad p)        {   bitmap = b;            photoToLoad = p;        }        public void run()         {             if(imageViewReused(photoToLoad))                 return;             if(bitmap!=null)                 photoToLoad.imageView.setImageBitmap(bitmap);             else                photoToLoad.imageView.setImageResource(stub_id);         }     }    /**     * 清除所有的缓存(包括内存和SD卡)     */    public void clearCache() {         memoryCache.clear();         fileCache.clear();     }    /**     * 只清除内存中的缓存     */    public void clearMemoryCache(){        memoryCache.clear();    }  } 

 

具体使用很简单:

ImageLoader  imageLoader = new ImageLoader(Activity.this)  ;

 imageLoader.DisplayImageWithNodefault(pic_url,imageVew,false); //不需要显示默认图片

 

全部源码下载链接:

http://download.csdn.net/detail/nanzhiwen666/5955391


 

 

 

 

 

 

 

原创粉丝点击