ListView异步加载图片实现思路
更新时间:2013年04月03日 14:33:02 作者:
用到ListView去加载数据,加载图片和文字是比较常见的,文字还好,图片从网络请求加载速度比较慢,以下是一个我在项目中使用到的异步加载图片的解决方案
在应用开发中,经常用到ListView去加载数据,加载图片和文字是比较常见的,文字还好,图片从网络请求加载速度比较慢,所以需要把图片的加载放到另一个线程中去执行,执行完了再更新UI线程。以下列出一个我在项目中使用到的异步加载图片的解决方案,代码没有上全,给出核心部分。
大致思路是这样:
1.利用软引用来缓存图片Bitmap,用图片的URL作为缓存查找的Key;
2.设两级缓存,一级是SoftReference,二级是本地SD卡;
3.如果两级缓存都没取到图片,则从服务器获取,并加入缓存;
4.加载完后通过回调接口通知UI更新;
以下是异步加载的关键代码,其中一些工具类没有给出,自己实现就可以,比如HttpRequest是我自己写的一个类。
public class AsyncImageLoader {
//Cache for image(Type String is the URL of image,the second parameter is soft reference)
private HashMap<String, SoftReference<Bitmap>> imageCache = null;
private Activity context;
public AsyncImageLoader(Activity context){
this.context = context;
imageCache = new HashMap<String, SoftReference<Bitmap>>();
}
public Bitmap loadImage(final ImageView imageView,final String imageURL,final ImageCallBack imageCallBack){
//If the cache contains the reference of bitmap then return
if (imageCache.containsKey(imageURL)) {
SoftReference<Bitmap> bitmapReference = imageCache.get(imageURL);
Bitmap bitmap = bitmapReference.get();
if (bitmap != null) {
return bitmap;
}
}
//Second cache,search local SD card
else {
String fileName = StringUtil.namePicture(imageURL);//获取文件名
boolean isExist = SystemUtils.findPhotoFromSDCard(Constant.INFO_PATH, fileName);
if (isExist) {//是否在SD卡存在图片
Bitmap bitmap = SystemUtils.getPhotoFromSDCard(Constant.INFO_PATH, fileName);
return bitmap;
}
}
final Handler myHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
imageCallBack.setImage(imageView, (Bitmap)msg.obj);
}
};
//If the bitmap not exists in cache or SD card,then get it from net
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
boolean isNetwork = SystemUtils.checkNetwork(context);
if (isNetwork) {
InputStream photoStream = HttpRequest.getImageStream(imageURL);//这里是我自己写的一个类,目的是通过URL地址从服务器获取图片输入流
Bitmap bitmap;
try {
bitmap = ImageTools.getResizeBitmap(photoStream, 128, 128);
if (bitmap != null) {
String fileName = StringUtil.namePicture(imageURL);
//Save image to SD card
SystemUtils.savePhotoToSDCard(bitmap, fileName, Constant.INFO_PATH);
//Put soft reference to cache
imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap));
//Send message to update UI
Message message = myHandler.obtainMessage(0, bitmap);
myHandler.sendMessage(message);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
return null;
}
/**
* Interface for load image
* @author Ryan
*
*/
public interface ImageCallBack{
//Set image for imageview through bitmap
public void setImage(ImageView imageView,Bitmap bitmap);
}
}
在ListView的adapter的getView方法中:
Bitmap bitmap1 = asyncImageLoader.loadImage(viewHolder.imageView1, url1, new ImageCallBack() {
@Override
public void setImage(ImageView imageView, Bitmap bitmap) {
// TODO Auto-generated method stub
imageView.setImageBitmap(bitmap);
}
});
if (bitmap1 != null) {
viewHolder.imageView1.setImageBitmap(bitmap1);
}else {
viewHolder.imageView1.setImageResource(R.drawable.image_bg);
}
其中asyncImageLoader是在adapter的构造方法中初始化的,形成一个缓存。通过这个机制就可以实现ListView的图片异步加载,在用户体验上比直接加载要感觉好很多,那样会造成界面卡顿。这里是加载一张图片的情况,如果ListView的item中的图片是不定的,有可能是一张、两张、三张,该用什么方式呢,大家可以思考一下,并可以一起讨论一下,包括实现ListView滚动时不加载数据也是优化ListView加载的必要步骤。
大致思路是这样:
1.利用软引用来缓存图片Bitmap,用图片的URL作为缓存查找的Key;
2.设两级缓存,一级是SoftReference,二级是本地SD卡;
3.如果两级缓存都没取到图片,则从服务器获取,并加入缓存;
4.加载完后通过回调接口通知UI更新;
以下是异步加载的关键代码,其中一些工具类没有给出,自己实现就可以,比如HttpRequest是我自己写的一个类。
复制代码 代码如下:
public class AsyncImageLoader {
//Cache for image(Type String is the URL of image,the second parameter is soft reference)
private HashMap<String, SoftReference<Bitmap>> imageCache = null;
private Activity context;
public AsyncImageLoader(Activity context){
this.context = context;
imageCache = new HashMap<String, SoftReference<Bitmap>>();
}
public Bitmap loadImage(final ImageView imageView,final String imageURL,final ImageCallBack imageCallBack){
//If the cache contains the reference of bitmap then return
if (imageCache.containsKey(imageURL)) {
SoftReference<Bitmap> bitmapReference = imageCache.get(imageURL);
Bitmap bitmap = bitmapReference.get();
if (bitmap != null) {
return bitmap;
}
}
//Second cache,search local SD card
else {
String fileName = StringUtil.namePicture(imageURL);//获取文件名
boolean isExist = SystemUtils.findPhotoFromSDCard(Constant.INFO_PATH, fileName);
if (isExist) {//是否在SD卡存在图片
Bitmap bitmap = SystemUtils.getPhotoFromSDCard(Constant.INFO_PATH, fileName);
return bitmap;
}
}
final Handler myHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
imageCallBack.setImage(imageView, (Bitmap)msg.obj);
}
};
//If the bitmap not exists in cache or SD card,then get it from net
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
boolean isNetwork = SystemUtils.checkNetwork(context);
if (isNetwork) {
InputStream photoStream = HttpRequest.getImageStream(imageURL);//这里是我自己写的一个类,目的是通过URL地址从服务器获取图片输入流
Bitmap bitmap;
try {
bitmap = ImageTools.getResizeBitmap(photoStream, 128, 128);
if (bitmap != null) {
String fileName = StringUtil.namePicture(imageURL);
//Save image to SD card
SystemUtils.savePhotoToSDCard(bitmap, fileName, Constant.INFO_PATH);
//Put soft reference to cache
imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap));
//Send message to update UI
Message message = myHandler.obtainMessage(0, bitmap);
myHandler.sendMessage(message);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
return null;
}
/**
* Interface for load image
* @author Ryan
*
*/
public interface ImageCallBack{
//Set image for imageview through bitmap
public void setImage(ImageView imageView,Bitmap bitmap);
}
}
在ListView的adapter的getView方法中:
复制代码 代码如下:
Bitmap bitmap1 = asyncImageLoader.loadImage(viewHolder.imageView1, url1, new ImageCallBack() {
@Override
public void setImage(ImageView imageView, Bitmap bitmap) {
// TODO Auto-generated method stub
imageView.setImageBitmap(bitmap);
}
});
if (bitmap1 != null) {
viewHolder.imageView1.setImageBitmap(bitmap1);
}else {
viewHolder.imageView1.setImageResource(R.drawable.image_bg);
}
其中asyncImageLoader是在adapter的构造方法中初始化的,形成一个缓存。通过这个机制就可以实现ListView的图片异步加载,在用户体验上比直接加载要感觉好很多,那样会造成界面卡顿。这里是加载一张图片的情况,如果ListView的item中的图片是不定的,有可能是一张、两张、三张,该用什么方式呢,大家可以思考一下,并可以一起讨论一下,包括实现ListView滚动时不加载数据也是优化ListView加载的必要步骤。
您可能感兴趣的文章:
- ListView异步加载图片实现思路(优化篇)
- 将选择的图片显示在listview中,并显示filename,path和type的简单实例
- Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案
- Android实现ListView异步加载图片的方法
- 新浪微博第三方登录界面上下拉伸图片之第三方开源PullToZoomListViewEx(一)
- 新浪微博第三方登录界面上下拉伸图片之第三方开源PullToZoomListViewEx(二)
- Android程序开发ListView+Json+异步网络图片加载+滚动翻页的例子(图片能缓存,图片不错乱)
- Android ListView异步加载图片方法详解
- C#下listview如何插入图片
相关文章
Android ActionBarActivity设置全屏无标题实现方法总结
这篇文章主要介绍了Android ActionBarActivity设置全屏无标题实现方法总结的相关资料,需要的朋友可以参考下2017-04-04android:descendantFocusability方法介绍
开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点2012-11-11Android Studio控制台出现中文乱码(方框)问题解决办法
这篇文章主要介绍了Android Studio控制台出现中文乱码(方框)问题解决办法的相关资料,需要的朋友可以参考下2017-06-06
最新评论