java 线程 listview_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> imageCache;// 图片对象缓存,key:图片的url

private Handler handler;// 界面Activity的Handler对象

public AsynImageLoader(Handler handler) {

imageCache = new HashMap>();

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 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> entry : imageCache.entrySet()) {

Bitmap bitmap = entry.getValue().get();

if (bitmap != null) {

bitmap.recycle();// 释放bitmap对象

}

}

imageCache.clear();

}

}

/**

* 加载图片并显示的线程

*/

private class LoaderThread extends Thread {

LinkedHashMap mTaskMap;// 需要加载图片并显示的图片视图对象任务链

private boolean mIsWait;// 标识是线程是否处于等待状态

public LoaderThread(ImageView imageView, String url) {

mTaskMap = new LinkedHashMap();

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));

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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值