android listview利用多线程异步加载图片并更新视图

一、ImageView异步加载类

package com.busap.netutils;

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 lizhen
 * 
 */
public final class AsynImageLoader {

	private LoaderThread thread;// 加载图片并发消息通知更新界面的线程
	private HashMap<String, SoftReference<Bitmap>> imageCache;// 图片对象缓存,key:图片的url
	private 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();
				}
			}
		}

		@Override
		public 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
							@Override
							public void run() {
								imageView.setImageBitmap(bitmap);
							}
						});
					}
				}
				if (mTaskMap.isEmpty()) {// 当任务队列中没有待处理的任务时,线程进入等待状态
					try {
						mIsWait = true;// 标识线程的状态,必须在wait()方法之前
						synchronized (this) {
							this.wait();// 保用线程进入等待状态,直到有新的任务被加入时通知唤醒
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

二、使用

Handler handler;
AsynImageLoader mImageAsynLoader;
mImageAsynLoader.loadBitmap(discount_icon,defaultBitmap);


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
1、Android显示GIF动画 GifView GifView 是一个为了解决android中现在没有直接显示gif的view,只能通过mediaplay来显示这个问题的项目,其用法和 ImageView一样,支持gif图片 使用方法:1-把GifView.jar加入你的项目。2-在xml中配置GifView的基本属性,GifView继承自View类,和Button、ImageView一样是一个UI控件。 如: 3-在代码中配置常用属性: // 从xml中得到GifView的句柄 gf1 = (GifView) findViewById(R.id.gif1); // 设置Gif图片源 gf1.setGifImage(R.drawable.gif1); // 添加监听器 gf1.setOnClickListener(this); // 设置显示的大小,拉伸或者压缩 gf1.setShowDimension(300, 300); // 设置加载方式:先加载后显示、边加载边显示、只显示第一帧再显示 gf1.setGifImageType(GifImageType.COVER); GifView的Jar包共有四个类: GifAction.java 观察者类,监视GIF是否加载成功 GifFrame.java 里面三个成员:当前图片、延时、下张Frame的链接。 GifDecoder.java 解码线程类 GifView.java 主类,包括常用方法,如GifView构造方法、设置图片源、延迟、绘制等。 2、Calendar.v0.5.0 是 Android 平台的一个日历显示组件。 3、CWAC EndlessAdapter 是 Android 上一个可以无限往下滑进行列表数据加载的控件。 4、Android Horizontal ListViewAndroid 上一个水平滑动的 ListView 组件。 5、Android ViewBadger 视图布局。 6、滑动刷新的ListView Android PullToRefresh 为 Android 应用提供一个向下滑动即刷新列表的功能,就两个目标文件。 7、pakerfeldt-android-viewflow 是 Android 平台上一个视图切换的效果库。ViewFlow 相当于 Android UI 部件提供水平滚动的 ViewGroup,使用 Adapter 进行条目绑定。 8、Android 导航菜单 RibbonMenu 是 Android 上的一个导航菜单组件。就三个目标文件,菜单项直接在 XML 中定义,可添加文本和图标。 9、Android的UI工具包 android-ui-utils 是一个工具包用来帮助设计和开发 Android 用户界面,包含三个单独的工具:Android Asset Studio用户界面原型模具,Android 设计预览,时常需要重复确认程序版面设计状况的 Android App 开发者,应该会爱上这个轻量级的 Java 程序:Andorid Design Preview 工具,通过 USB 连接之后,只要简单的在计算机中选取您想要显示的程序版面范围,就可将镜像结果直接显示于手机装置之上。 10、Android的ui开发类库 GreenDroid 是一个Android的ui开发类库,能够使你的Android开发更加简便和快捷。 11、Android滑动式菜单 SlidingMenu 是 Android 上实现类似 Facebook 和 Path 2.0 滑动式菜单的组件。 12、AsyncImageView 是 Android 上的一个异步从网络上获取图片并进行浏览的开源组件,可自动在本地进行缓存。该项目是 GreenDroid 的一部分。 13、仿Path按钮动画效果 PathButton 仿照Path应用首页左下角的Button动画效果写了个简单的Demo,由于数学不好,坐标总是和理想有出入,只是大致实现了动画效果,若果有人能把坐标算对,那么修改我的demo就能做成类似Path的那种动画效果!希望大家出点力帮着优化一下,并分享出来! 14、Android Intent开发包 OpenIntents Ope

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值