package cn.jd3g.utils;  002    003 import java.lang.ref.SoftReference;  004 import java.util.HashMap;  005 import java.util.LinkedHashMap;  006 import java.util.Map.Entry;  007    008 import android.graphics.Bitmap;  009 import android.os.Handler;  010 import android.util.Log;  011 import android.widget.ImageView;  012    013 /**  014  * 利用多线程异步加载图片并更新视图  015  *   016  * @author xfzhang  017  *   018  */ 019 public final class AsynImageLoader {  020    021     private LoaderThread thread;// 加载图片并发消息通知更新界面的线程  022     private HashMap<String, SoftReference<Bitmap>> imageCache;// 图片对象缓存,key:图片的url  023     private Handler handler;// 界面Activity的Handler对象  024    025     public AsynImageLoader(Handler handler) {  026         imageCache = new HashMap<String, SoftReference<Bitmap>>();  027         this.handler = handler;  028     }  029    030     /**  031      * 加载图片前显示到指定的ImageView中,图片的url保存在视图对象的Tag中  032      *   033      * @param imageView  034      *            要显示图片的视图  035      * @param defaultBitmap  036      *            加载需要显示的提示正在加载的默认图片对象  037      */ 038     public void loadBitmap(ImageView imageView, Bitmap defaultBitmap) {  039         // 图片所对应的url,这个值在加载图片过程中很可能会被改变  040         String url = (String) imageView.getTag();  041         if (imageCache.containsKey(url)) {// 判断缓存中是否有  042             SoftReference<Bitmap> softReference = imageCache.get(url);  043             Bitmap bitmap = softReference.get();  044             if (bitmap != null) {// 如果图片对象不为空,则可挂接更新视图,并返回  045                 imageView.setImageBitmap(bitmap);  046                 return;  047             } else {// 如果为空,需要将其从缓存中删除(其bitmap对象已被回收释放,需要重新加载)  048                 Log.e("TAG", "cache bitmap is null");  049                 imageCache.remove(url);  050             }  051         }  052         imageView.setImageBitmap(defaultBitmap);// 先显示一个提示正在加载的图片  053         if (thread == null) {// 加载线程不存在,线程还未启动,需要新建线程并启动  054             thread = new LoaderThread(imageView, url);  055             thread.start();  056         } else {// 如果存在,就调用线程对象去加载  057             thread.load(imageView, url);  058         }  059    060     }  061    062     /**  063      * 释放缓存中所有的Bitmap对象,并将缓存清空  064      */ 065     public void releaseBitmapCache() {  066         if (imageCache != null) {  067             for (Entry<String, SoftReference<Bitmap>> entry : imageCache.entrySet()) {  068                 Bitmap bitmap = entry.getValue().get();  069                 if (bitmap != null) {  070                     bitmap.recycle();// 释放bitmap对象  071                 }  072             }  073             imageCache.clear();  074         }  075     }  076    077     /**  078      * 加载图片并显示的线程  079      */ 080     private class LoaderThread extends Thread {  081    082         LinkedHashMap<String, ImageView> mTaskMap;// 需要加载图片并显示的图片视图对象任务链  083         private boolean mIsWait;// 标识是线程是否处于等待状态  084    085         public LoaderThread(ImageView imageView, String url) {  086             mTaskMap = new LinkedHashMap<String, ImageView>();  087             mTaskMap.put(url, imageView);  088         }  089    090         /**  091          * 处理某个视图的更新显示  092          *   093          * @param imageView  094          */ 095         public void load(ImageView imageView, String url) {  096             mTaskMap.remove(imageView);// 任务链中可能有,得先删除  097             mTaskMap.put(url, imageView);// 将其添加到任务中  098             if (mIsWait) {// 如果线程此时处于等待得唤醒线程去处理任务队列中待处理的任务  099                 synchronized (this) {// 调用对象的notify()时必须同步  100                     this.notify();  101                 }  102             }  103         }  104    105         @Override 106         public void run() {  107             while (mTaskMap.size() > 0) {// 当队列中有数据时线程就要一直运行,一旦进入就要保证其不会跳出循环  108                 mIsWait = false;  109                 final String url  = mTaskMap.keySet().iterator().next();  110                 final ImageView imageView = mTaskMap.remove(url);  111                 if (imageView.getTag() == url) {// 判断视图有没有复用(一旦ImageView被复用,其tag值就会修改变)  112                     final Bitmap bitmap = MyConnection.getBitmapByUrl(url);// 此方法应该是从网络或sd卡中加载  113                     try {  114                         Thread.sleep(1000);// 模拟网络加载数据时间  115                     } catch (InterruptedException e1) {  116                         e1.printStackTrace();  117                     }  118                     // 将加载的图片放入缓存map中  119                     imageCache.put(url, new SoftReference<Bitmap>(bitmap));  120                     if (url == imageView.getTag()) {// 再次判断视图有没有复用  121                         handler.post(new Runnable() {// 通过消息机制在主线程中更新UI  122                             @Override 123                             public void run() {  124                                 imageView.setImageBitmap(bitmap);  125                             }  126                         });  127                     }  128                 }  129                 if (mTaskMap.isEmpty()) {// 当任务队列中没有待处理的任务时,线程进入等待状态  130                     try {  131                         mIsWait = true;// 标识线程的状态,必须在wait()方法之前  132                         synchronized (this) {  133                             this.wait();// 保用线程进入等待状态,直到有新的任务被加入时通知唤醒  134                         }  135                     } catch (InterruptedException e) {  136                         e.printStackTrace();  137                     }  138                 }  139             }  140         }  141     }  142 } 查看源码打印?01 private class ProductListAdapter extends BaseAdapter {  02    03         private AsynImageLoader mImageAsynLoader;  04    05         public ProductListAdapter() {  06             mImageAsynLoader = new AsynImageLoader(mHandler);  07         }  08    09         @Override 10         public int getCount() {  11             int size = Math.min(mLastItemViewIndex + 1, mDataList.size());  12             mLastItemViewIndex = size - 1;  13             return size;  14         }  15    16         @Override 17         public Object getItem(int position) {  18             return mDataList.get(position);  19         }  20    21         @Override 22         public long getItemId(int position) {  23             return position;  24         }  25    26         @Override 27         public View getView(int position, View convertView, ViewGroup parent) {  28             if (convertView == null) {  29                 convertView = getLayoutInflater().inflate(R.layout.product_list_item,  30                         null);  31             }  32             ImageView imageView = (ImageView) convertView  33                     .findViewById(R.id.iv_item_product_image);  34             Map<String, String> map = mDataList.get(position);  35 //存放图片所对应的url  36             imageView.setTag(map.get("product_pic_address"));  37             mImageAsynLoader.loadBitmap(imageView, mDefautBitmap);  38             return convertView;  39         }  40     } 

更多相关文章

  1. Android(安卓)-- 图片画画板(canvas、paint、bitmap)
  2. android 线程优先级设置方法
  3. android:ImageView,访问网上图片并显示出来
  4. android 下载文件图片圆形进度条
  5. 26、Android之Handler异步消息处理机制
  6. Android(安卓)--- 图片处理的方法
  7. Android(安卓)调用Camera和相册
  8. android三种载入图片方式
  9. Android(安卓)HTTP GET/POST

随机推荐

  1. 用x种方式求第n项斐波那契数,99%的人只会
  2. CAP定理
  3. Hash Cluster Table 研究
  4. 【故障处理】 DBCA建库报错CRS-2566
  5. 【ASM】ASMLIB 系列
  6. 磁盘组不能自动挂载
  7. 【OGG】OGG基础知识整理
  8. 【OGG】关于在一套复制环境中使用不同版
  9. ORA-01578和ORA-26040--NOLOGGING操作引
  10. 【故障处理】序列cache值过小导致CPU利用