Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1071546
  • 博文数量: 403
  • 博客积分: 10272
  • 博客等级: 上将
  • 技术积分: 4407
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 14:22
文章分类

全部博文(403)

文章存档

2012年(403)

分类: 嵌入式

2012-03-03 11:26:24

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

阅读(943) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~