解决ListView异步加载图片错乱问题 .
发一个异步图片加载控件。网上也有大把的异步网络加载图片的控件,但是有一个问题,异步加载会造成列表中的图片混乱,因为列表的每一项的View都可能被重用,异步加载的时候多个异步线程引用到了同一个View将造成图片加载错乱。该控件解决这个问题:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.widget.ImageView; /**
* 异步图片控件
* 使用:new AsyncImageView().asyncLoadBitmapFromUrl("http://xxxx","缓存路径"){
*
* @author gaoomei@gmail.com
* @site http://obatu.sinaapp.com
* @version 1.0
* @2011-12-3
*/
public class AsyncImageView extends ImageView { /**
* 异步task加载器
*/
private AsyncLoadImage mAsyncLoad; /**
* 下载回来的图片缓存存活时间,单位:秒(s),默认30分钟
*/
private long mCacheLiveTime = 1800; public AsyncImageView(Context context) {
super(context);
} public AsyncImageView(Context context, AttributeSet attrs) {
super(context, attrs);
} public AsyncImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} /**
*
*/
@Override
public void setImageDrawable(Drawable drawable) {
if (mAsyncLoad != null) {
mAsyncLoad.cancel(true);
mAsyncLoad = null;
}
super.setImageDrawable(drawable);
} /**
* 重写下面几个设置图片资源的方法,目地是取消网络加载
*/
@Override
public void setImageResource(int resId) {
cancelLoad();
super.setImageResource(resId);
} @Override
public void setImageURI(Uri uri) {
cancelLoad();
super.setImageURI(uri);
} @Override
public void setImageBitmap(Bitmap bitmap) {
cancelLoad();
super.setImageBitmap(bitmap);
} /**
* 取消正在进行的异步task
*/
public void cancelLoad() {
if (mAsyncLoad != null) {
mAsyncLoad.cancel(true);
mAsyncLoad = null;
}
} /**
* 设置图片存活时间
*
* @param second
* 存活时间,单位【秒】,如果等于0或null,则不缓存
*/
public void setCacheLiveTime(long second) {
if (second == 0) {
this.mCacheLiveTime = 0;
} else if (second >= 0) {
this.mCacheLiveTime = second * 1000;
}
} /**
* 从网络异步加载
*
* @param url
* @param saveFileName
*/
public void asyncLoadBitmapFromUrl(String url, String saveFileName) {
if (mAsyncLoad != null) {
mAsyncLoad.cancel(true);
}
// AsyncTask不可重用,所以每次重新实例
mAsyncLoad = new AsyncLoadImage();
mAsyncLoad.execute(url, saveFileName);
} /**
* 异步加载器
*/
private class AsyncLoadImage extends AsyncTask {
/**
* 是否取消
*/
private boolean isCancel = false; @Override
protected Bitmap doInBackground(String... params) {
if (isCancel) {
return null;
}
String url = params[0];
String fileName = params[1];
try {
return getBitmap(url, fileName);
} catch (IOException e) {
e.printStackTrace();
}
return null;
} @Override
protected void onCancelled() {
System.out.println("async load imgae cancel");
isCancel = true;
} @Override
protected void onPostExecute(Bitmap result) {
if (!isCancel && result != null) {
AsyncImageView.this.setImageBitmap(result);
}
}
} /**
* 下载图片
*
* @param urlString
* url下载地址
* @param fileName
* 缓存文件路径
* @throws IOException
*/
private Bitmap getBitmap(String urlString, String fileName)
throws IOException {
if (fileName == null || fileName.trim().isEmpty()) {
InputStream input = getBitmapInputStreamFromUrl(urlString);
return BitmapFactory.decodeStream(input);
} File file = new File(fileName);
if (!file.isFile()
|| (mCacheLiveTime > 0 && (System.currentTimeMillis()
- file.lastModified() > mCacheLiveTime))) {
InputStream input = getBitmapInputStreamFromUrl(urlString);
file = saveImage(input, fileName);
// 如果文件结构创建失败,则直接从输入流解码图片
if (file == null || !file.exists() || !file.canWrite()
|| !file.canRead()) {
return BitmapFactory.decodeStream(input);
}
}
return BitmapFactory.decodeFile(file.getAbsolutePath());
} /**
* 下载图片,输入InputStream
*
* @param urlString
* @return
* @throws IOException
*/
private InputStream getBitmapInputStreamFromUrl(String urlString)
throws IOException {
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
connection.setConnectTimeout(25000);
connection.setReadTimeout(90000);
return connection.getInputStream();
} /**
* 从输入流保存图片到文件系统
*
* @param fileName
* @param input
* @return
*/
private File saveImage(InputStream input, String fileName) {
if (fileName.trim().isEmpty() || input == null) {
return null;
}
File file = new File(fileName);
OutputStream output = null;
try {
file.getParentFile().mkdirs();
if (file.exists() && file.isFile()) {
file.delete();
}
if (!file.createNewFile()) {
return null;
}
output = new FileOutputStream(file);
byte[] buffer = new byte[4 * 1024];
do {
// 循环读取
int numread = input.read(buffer);
if (numread == -1) {
break;
}
output.write(buffer, 0, numread);
} while (true);
output.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e2) {
e2.printStackTrace();
}
}
return file;
}
}
解决ListView异步加载图片错乱问题 .的更多相关文章
- Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法
Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...
- Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案
我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...
- android listview 异步加载图片并防止错位
网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertVie ...
- listview异步加载图片并防止错位
android listview 异步加载图片并防止错位 网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 conver ...
- ListView异步加载图片,完美实现图文混排
昨天参加一个面试,面试官让当场写一个类似于新闻列表的页面,文本数据和图片都从网络上获取,想起我还没写过ListView异步加载图片并实现图文混排效果的文章,so,今天就来写一下,介绍一下经验. Lis ...
- Android 实现ListView异步加载图片
ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...
- 又优化了一下 Android ListView 异步加载图片
写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看 ...
- ListView异步加载图片
ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...
- Listview 异步加载图片之优化篇(有图有码有解释)
在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...
随机推荐
- 像素,分辨率,PPI(像素密度),BPP 扫盲
像素于分辨率 像素,又称画素,为图像显示的基本单位,译自英文“pixel”,pix是英语单词picture的常用简写,加上英语单词“元素”element,就得到pixel,故“像素”表示“图像元素”之 ...
- 《算法问题实战策略》——chaper9——动态规划法技巧
Q1: 数字游戏: 两个人(A.B)用n个整数排成的一排棋盘玩游戏,游戏从A开始,每个人有如下操作: (1) 拿走棋盘最右侧或者最左侧的棋子,被拿走的数字从棋盘中抹掉. (2) 棋盘中还剩 ...
- 突破LVS瓶颈,LVS Cluster部署(OSPF + LVS) - lxcong的运维技术 - 开源中国社区
突破LVS瓶颈,LVS Cluster部署(OSPF + LVS) - lxcong的运维技术 - 开源中国社区 突破LVS瓶颈,LVS Cluster部署(OSPF + LVS)
- 从m个数中取top n
将题目具体一点,例如,从100个数中取出从大到小排前10的数 方法1:使用快速排序 因为快速排序一趟下来,小于K的数都在K的前面,大于K的数都在K的后面 如果,小于K的数有35个,大于K的数有64个 ...
- shared pool详解
共享池shared pool的概念用户提交的命令:解析.执行用户命令的解析解析的过程是一个相当复杂的过程,它要考虑各种可能的异常情况比如SQL语句涉及到的对象不存在.提交的用户没有权限等等而且还需要考 ...
- git 分支策略
转 http://www.ruanyifeng.com/blog/2012/07/git.html 作者: 阮一峰 如果你严肃对待编程,就必定会使用"版本管理系统"(Versio ...
- springboot +spring security4 +thymeleaf 后台管理系统
需求:一个后台管理系统,现在用的springboot 微框架比较多, 所以这里也使用了, 后台权限用 spring security ,之前以前觉得听复杂 . 后来发现还是蛮简单的, 看了源代码之后. ...
- Python程序的执行原理(转载)
Python程序的执行原理 2013-09-17 10:35 佚名 tech.uc 1. 过程概述 Python先把代码(.py文件)编译成字节码,交给字节码虚拟机,然后虚拟机一条一条执行字节码指令 ...
- 接口作为参数,不同的接口调用不同的方法,例如:输出“I love Game”或输出“我喜欢游戏”
接口的思想:在于可以增加很多类都需要实现的功能.比如:各式各样的商品,可能隶属不同公司,但工商部门都必须具有显示商标的功能(实现同一接口).商标的具体制作由各个公司自己去实现. 给其他类去实现,不同的 ...
- 程序猿接私活经验总结,来自csdn论坛语录
下面为网上摘录,以做笔记: 但是到网上看看,似乎接私活也有非常多不easy,技术问题本身是个因素,还有非常多有技术的人接私活时被骗,或者是合作到最后以失败告终,所以想请有经验的大侠们出来指点一下,接私 ...