package cn.jd3g.utils;import java.lang.ref.SoftReference;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map.Entry;import android.graphics.Bitmap;import android.os.Handler;import android.util.Log;import android.widget.ImageView;/** * 利用多线程异步加载图片并更新视图 *  * @author xfzhang *  */public final class AsynImageLoader {private LoaderThread thread;// 加载图片并发消息通知更新界面的线程private HashMap<String, SoftReference<Bitmap>> imageCache;// 图片对象缓存,key:图片的urlprivate Handler handler;// 界面Activity的Handler对象public AsynImageLoader(Handler handler) {imageCache = new HashMap<String, SoftReference<Bitmap>>();this.handler = handler;}/** * 加载图片前显示到指定的ImageView中,图片的url保存在视图对象的Tag中 *  * @param imageView *            要显示图片的视图 * @param defaultBitmap *            加载需要显示的提示正在加载的默认图片对象 */public void loadBitmap(ImageView imageView, Bitmap defaultBitmap) {// 图片所对应的url,这个值在加载图片过程中很可能会被改变String url = (String) imageView.getTag();if (imageCache.containsKey(url)) {// 判断缓存中是否有SoftReference<Bitmap> softReference = imageCache.get(url);Bitmap bitmap = softReference.get();if (bitmap != null) {// 如果图片对象不为空,则可挂接更新视图,并返回imageView.setImageBitmap(bitmap);return;} else {// 如果为空,需要将其从缓存中删除(其bitmap对象已被回收释放,需要重新加载)Log.e("TAG", "cache bitmap is null");imageCache.remove(url);}}imageView.setImageBitmap(defaultBitmap);// 先显示一个提示正在加载的图片if (thread == null) {// 加载线程不存在,线程还未启动,需要新建线程并启动thread = new LoaderThread(imageView, url);thread.start();} else {// 如果存在,就调用线程对象去加载thread.load(imageView, url);}}/** * 释放缓存中所有的Bitmap对象,并将缓存清空 */public void releaseBitmapCache() {if (imageCache != null) {for (Entry<String, SoftReference<Bitmap>> entry : imageCache.entrySet()) {Bitmap bitmap = entry.getValue().get();if (bitmap != null) {bitmap.recycle();// 释放bitmap对象}}imageCache.clear();}}/** * 加载图片并显示的线程 */private class LoaderThread extends Thread {LinkedHashMap<String, ImageView> mTaskMap;// 需要加载图片并显示的图片视图对象任务链private boolean mIsWait;// 标识是线程是否处于等待状态public LoaderThread(ImageView imageView, String url) {mTaskMap = new LinkedHashMap<String, ImageView>();mTaskMap.put(url, imageView);}/** * 处理某个视图的更新显示 *  * @param imageView */public void load(ImageView imageView, String url) {mTaskMap.remove(imageView);// 任务链中可能有,得先删除mTaskMap.put(url, imageView);// 将其添加到任务中if (mIsWait) {// 如果线程此时处于等待得唤醒线程去处理任务队列中待处理的任务synchronized (this) {// 调用对象的notify()时必须同步this.notify();}}}@Overridepublic void run() {while (mTaskMap.size() > 0) {// 当队列中有数据时线程就要一直运行,一旦进入就要保证其不会跳出循环mIsWait = false;final String url  = mTaskMap.keySet().iterator().next();final ImageView imageView = mTaskMap.remove(url);if (imageView.getTag() == url) {// 判断视图有没有复用(一旦ImageView被复用,其tag值就会修改变)final Bitmap bitmap = MyConnection.getBitmapByUrl(url);// 此方法应该是从网络或sd卡中加载try {Thread.sleep(1000);// 模拟网络加载数据时间} catch (InterruptedException e1) {e1.printStackTrace();}// 将加载的图片放入缓存map中imageCache.put(url, new SoftReference<Bitmap>(bitmap));if (url == imageView.getTag()) {// 再次判断视图有没有复用handler.post(new Runnable() {// 通过消息机制在主线程中更新UI@Overridepublic void run() {imageView.setImageBitmap(bitmap);}});}}if (mTaskMap.isEmpty()) {// 当任务队列中没有待处理的任务时,线程进入等待状态try {mIsWait = true;// 标识线程的状态,必须在wait()方法之前synchronized (this) {this.wait();// 保用线程进入等待状态,直到有新的任务被加入时通知唤醒}} catch (InterruptedException e) {e.printStackTrace();}}}}}}

更多相关文章

  1. android在处理一写图片资源
  2. android 利用Canvas显示局部图片
  3. android 上传/下载 图片
  4. android如何在子线程中更新UI
  5. android UI控件之webview控件使用实例:加载网页到webview中
  6. android截取屏幕图片
  7. android ImageLoader加载本地图片的工具类

随机推荐

  1. Android(安卓)事件处理
  2. 仿Android6.0联系人列表
  3. Android电话拨打流程源码分析
  4. 为什么说Android令人沮丧!?
  5. Android状态check、focused、pressed、se
  6. Android安装以及Eclipse插件(Google Andr
  7. Ubuntu 试用Android(安卓)L版本
  8. android 10 高通 图标名称双行显示
  9. Android收藏商品/关注商品
  10. android开源新闻小程序、3D翻转公告效果