Android ListView图片异步加载显示
2014-10-05 14:40
567 查看
模拟android中的消息机制实现图片的异步加载和动态显示
packagecn.jd3g.utils; importjava.lang.ref.SoftReference; importjava.util.HashMap; importjava.util.LinkedHashMap; importjava.util.Map.Entry; importandroid.graphics.Bitmap; importandroid.os.Handler; importandroid.util.Log; importandroid.widget.ImageView; /** * 利用多线程异步加载图片并更新视图 * * @author xfzhang * */ publicfinal class AsynImageLoader { privateLoaderThread thread;// 加载图片并发消息通知更新界面的线程 privateHashMap<String, SoftReference<Bitmap>> imageCache;// 图片对象缓存,key:图片的url privateHandler handler;// 界面Activity的Handler对象 publicAsynImageLoader(Handler handler) { imageCache = newHashMap<String, SoftReference<Bitmap>>(); this.handler = handler; } /** * 加载图片前显示到指定的ImageView中,图片的url保存在视图对象的Tag中 * * @param imageView * 要显示图片的视图 * @param defaultBitmap * 加载需要显示的提示正在加载的默认图片对象 */ publicvoid 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 = newLoaderThread(imageView, url); thread.start(); } else{// 如果存在,就调用线程对象去加载 thread.load(imageView, url); } } /** * 释放缓存中所有的Bitmap对象,并将缓存清空 */ publicvoid 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(); } } /** * 加载图片并显示的线程 */ privateclass LoaderThread extendsThread { LinkedHashMap<String, ImageView> mTaskMap;// 需要加载图片并显示的图片视图对象任务链 privateboolean mIsWait;// 标识是线程是否处于等待状态 publicLoaderThread(ImageView imageView, String url) { mTaskMap = newLinkedHashMap<String, ImageView>(); mTaskMap.put(url, imageView); } /** * 处理某个视图的更新显示 * * @param imageView */ publicvoid load(ImageView imageView, String url) { mTaskMap.remove(imageView);// 任务链中可能有,得先删除 mTaskMap.put(url, imageView);// 将其添加到任务中 if(mIsWait) {// 如果线程此时处于等待得唤醒线程去处理任务队列中待处理的任务 synchronized(this) {// 调用对象的notify()时必须同步 this.notify(); } } } @Override publicvoid run() { while(mTaskMap.size() > 0) {// 当队列中有数据时线程就要一直运行,一旦进入就要保证其不会跳出循环 mIsWait = false; finalString url = mTaskMap.keySet().iterator().next(); finalImageView imageView = mTaskMap.remove(url); if(imageView.getTag() == url) {// 判断视图有没有复用(一旦ImageView被复用,其tag值就会修改变) finalBitmap bitmap = MyConnection.getBitmapByUrl(url);// 此方法应该是从网络或sd卡中加载 try{ Thread.sleep(1000);// 模拟网络加载数据时间 } catch(InterruptedException e1) { e1.printStackTrace(); } // 将加载的图片放入缓存map中 imageCache.put(url, newSoftReference<Bitmap>(bitmap)); if(url == imageView.getTag()) {// 再次判断视图有没有复用 handler.post(newRunnable() {// 通过消息机制在主线程中更新UI @Override publicvoid run() { imageView.setImageBitmap(bitmap); } }); } } if(mTaskMap.isEmpty()) {// 当任务队列中没有待处理的任务时,线程进入等待状态 try{ mIsWait = true;// 标识线程的状态,必须在wait()方法之前 synchronized(this) { this.wait();// 保用线程进入等待状态,直到有新的任务被加入时通知唤醒 } } catch(InterruptedException e) { e.printStackTrace(); } } } } } }
<span style="font-size:14px;">privateclass ProductListAdapter extendsBaseAdapter { privateAsynImageLoader mImageAsynLoader; publicProductListAdapter() { mImageAsynLoader = newAsynImageLoader(mHandler); } @Override publicint getCount() { intsize = Math.min(mLastItemViewIndex + 1, mDataList.size()); mLastItemViewIndex = size - 1; returnsize; } @Override publicObject getItem(intposition) { returnmDataList.get(position); } @Override publiclong getItemId(intposition) { returnposition; } @Override publicView getView(intposition, View convertView, ViewGroup parent) { if(convertView == null) { convertView = getLayoutInflater().inflate(R.layout.product_list_item, null); } ImageView imageView = (ImageView) convertView .findViewById(R.id.iv_item_product_image); Map<String, String> map = mDataList.get(position); //存放图片所对应的url imageView.setTag(map.get("product_pic_address")); mImageAsynLoader.loadBitmap(imageView, mDefautBitmap); returnconvertView; } }</span>
相关文章推荐
- Android ListView图片异步加载显示
- Android开发之listview优化+图片异步加载+避免图片显示闪烁(修改版)
- Android listview异步加载图片(线程池,内存缓存,SD卡缓存)优化显示
- Android实习04:ListView网络异步加载图片的优化显示(2)
- Android:ListView异步加载图片(实现网络下载、存储本地、缓存内存、压缩显示)
- android ListView 重写 SimpleAdapter 显示图片 异步加载及文字处理
- 文章标题android之listview异步加载图片时显示加载进度ProgressBar
- android ListView利用SimpleAdapter显示特定布局并且异步加载网络图片
- Android实习03:ListView网络异步加载图片的优化显示(1)
- Android之ListView异步加载图片且仅显示可见子项中的图片
- Android之ListView异步加载图片且仅显示可见子项中的图片
- android ListView 异步加载图片
- android开发--ListView+Json+异步网络图片加载+滚动翻页的例子(图片能缓存,图片不错乱)
- Android实现ListView异步加载图片+缓存+线程池管理
- android listview分页异步加载图片及图片缓存
- android ListView异步加载图片(双缓存)
- android listview 滚动时异步加载图片的问题
- Android实现ListView异步加载图片
- 转载 Android实现ListView异步加载图片
- Android实现ListView异步加载图片