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:图片的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();
}
}
}
}
}
}
分享到:
相关推荐
在这个"Android异步加载图片例子"中,我们将探讨如何在Android应用中实现这一功能。 首先,我们需要理解Android的主线程(UI线程)与工作线程的区别。主线程负责处理用户界面交互,而工作线程则用于执行耗时操作,...
本资料包主要讲解了如何使用`AsyncTask`进行异步加载图片,这对于在UI线程中保持流畅用户体验至关重要。 `AsyncTask`是Android SDK中的一个类,它为开发者提供了简单的多线程和回调功能。它的核心思想是将长时间...
然而,在实际开发中,当我们需要在RecyclerView中异步加载图片时,可能会遇到图片显示乱序的问题。本文将深入探讨这个问题及其解决方案。 首先,我们来理解为什么会出现图片乱序的现象。这是因为RecyclerView在滚动...
Android 演示异步加载图片的实现 附源代码,这里主要是演示ListView的异步加载图片功能,异步加载一个view时,如果view里面有EditText,EditText在每次加载view都会触发焦点,这时候异步就会出错。可能我这样说不太...
在Android应用开发中,图片加载是一项常见的任务,尤其是在处理大量图片或者网络图片时,为了提供良好的用户体验,我们通常会采用异步加载的方式。本篇将深入探讨Android平台上的图片异步加载策略,以及如何加载网络...
本文将深入探讨Android ListView中异步加载图片的策略、常见问题以及解决方案。 首先,我们要理解异步加载的基本原理。异步加载是指在后台线程中执行耗时操作,如加载图片,而主线程则继续处理用户交互,保证界面...
在GridView中异步加载网络图片是一项重要的技能,特别是在构建图片丰富的应用如相册或社交媒体应用时。本示例适用于API级别17及以上,因为它是针对Android 4.2(Jelly Bean)及更高版本设计的。 1. ** GridView的...
这里的“android listView 异步加载图片”指的是在不阻塞UI线程的情况下,从网络、本地存储或其他来源加载图片到ListView中的技术。 这篇名为“ImageLoader”的Java文件很可能就是一个实现图片异步加载的工具类。在...
本文将详细介绍 Android 中实现 ListView 异步加载图片的方法,并对相关的技术概念进行解释。 1. 异步加载图片的必要性 在 Android 应用程序中,加载图片是一个耗时的操作,特别是在 ListView 中。如果不使用异步...
在Android开发中,异步加载图片是一项至关重要的技术,它能显著提升用户体验,尤其是在处理大量图片数据时。这个"Android中实现异步加载图片的Demo"展示了如何在Android应用中高效地加载和显示图片,无论是从本地...
"Android异步加载图片"是一个常见的需求,它涉及到用户体验优化、内存管理以及线程安全等多个方面。这里我们将深入探讨这个主题,并结合提供的"ImageLoader-develop"可能是一个图片加载库的源码,来讲解相关的知识点...
综上所述,Android异步加载图片和缓存策略是提升应用性能的关键技术。通过合理使用工作线程和缓存机制,可以显著改善用户体验,降低系统负载。在实际开发中,选择合适的图片加载库,并结合最佳实践,能够帮助我们...
Android 异步加载图片,对ListView的异步加载图片的功能演示,主要根据url读取图片返回流的方法。为了方便演示,将请求图片的链接先固定,每读取好一个图片就更新,界面比较简单,当然你可以做成比较好的,像很多好...
总的来说,Android-Universal-Image-Loader为Android开发者提供了一种高效、灵活的图片异步加载解决方案,无论是ListView、GridView还是ViewPager,都可以通过其强大的功能提升用户体验。在实际开发中,掌握这个库的...
在Android应用开发中,异步加载图片是一项常见的需求,特别是在处理大数据量的图像时,如在GridView或ListView中展示图片。`AsyncTask`是Android提供的一种轻量级的多线程解决方案,它允许开发者在后台执行耗时操作...
总的来说,Android异步加载图片缓存优化是通过合理利用内存和磁盘资源,配合高效的异步处理,为用户提供流畅的图片浏览体验,同时避免了由于大图加载引发的内存问题。开发者可以通过学习这个压缩包中的源码和文档,...
"Android中ListView全面完美的网络图片异步加载"这一主题正是解决这些问题的关键。 首先,我们需要理解异步加载的概念。异步加载意味着在后台线程处理耗时操作,如下载和解码图片,而不是在主线程中执行,这样可以...
首先,Android异步加载图片的目标是将耗时的网络请求或本地文件读取操作放在后台线程,以防止阻塞主线程。Android提供了一些工具和库来帮助开发者实现这一目标,如AsyncTask、Handler、Loader等。在这个例子中,我们...
本文将详细介绍如何在ListView中实现图片的异步加载,并且在用户拖动时不加载,以提高滚动流畅性。 一、异步加载原理 异步加载是指在后台线程中执行耗时操作,例如网络请求或解码图片,避免阻塞主线程。Android提供...