发一个异步图片加载控件。网上也有大把的异步网络加载图片的控件,但是有一个问题,异步加载会造成列表中的图片混乱,因为列表的每一项的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异步加载图片错乱问题 .的更多相关文章

  1. Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法

    Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...

  2. Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

    我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...

  3. android listview 异步加载图片并防止错位

    网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertVie ...

  4. listview异步加载图片并防止错位

    android listview 异步加载图片并防止错位 网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 conver ...

  5. ListView异步加载图片,完美实现图文混排

    昨天参加一个面试,面试官让当场写一个类似于新闻列表的页面,文本数据和图片都从网络上获取,想起我还没写过ListView异步加载图片并实现图文混排效果的文章,so,今天就来写一下,介绍一下经验. Lis ...

  6. Android 实现ListView异步加载图片

    ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...

  7. 又优化了一下 Android ListView 异步加载图片

    写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看 ...

  8. ListView异步加载图片

    ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码: package cn.wangmeng.test; ...

  9. Listview 异步加载图片之优化篇(有图有码有解释)

    在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...

随机推荐

  1. 把测试app打包成ipa文件

    我终于把我的程序放到我的touch上了,其实把app放到touch上还有很多办法,这篇教程是主要讲怎么把app注册了,然后打包成一个ipa文件的. 先上官方文档:https://developer.a ...

  2. Oracle设计规范!

    Oracle设计规范! 一哥们整理的Oracle的设计规范,相当的不错,贴这以备后续之需! 目录 1.数据库模型设计方法规范 1.1.数据建模原则性规范 1.2.实体型之间关系认定规范 1.3.范式化 ...

  3. OpenFlow能解决私有云网络VLAN问题么

    本文转载自:http://network.51cto.com/art/201202/314310.htm 在关于私有云网络的文章中,我们首先探讨了物理网络是否影响私有云.本文我们将讨论如何通过软件定义 ...

  4. 如何使用TcpDump抓取远程主机的流量并回显到本地的WireShark上

    ssh -t username@remoteip "echo rootpassword | sudo -S tcpdump -i eth0 -A '(tcp[((tcp[12:1] & ...

  5. 爬虫技术浅析 | WooYun知识库

    爬虫技术浅析 | WooYun知识库 爬虫技术浅析 好房通ERP | 房产中介软件最高水准领导者 undefined

  6. Java反射获取类和对象信息全解析

    反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题. 在两个人协作开发时,你只要知道对方的类名就可以进行初步的开发了. 获取类对象 Class.f ...

  7. Docker官方文档翻译之入门

    转自:http://www.cnblogs.com/vikings-blog/p/3958091.html Docker学习总结之docker入门 Understanding Docker 以下均翻译 ...

  8. 用js判断一个复选框是否被选中

    <html> <head>        <title>            复选框全选.全不选.反选.必选一个        </title>    ...

  9. kafka consumer频繁reblance

    转载请注明地址http://www.cnblogs.com/dongxiao-yang/p/5417956.html 结论与下文相同,kafka不同topic的consumer如果用的groupid名 ...

  10. 小程序原理,生成SQL SERVER 2008 数据库所有表的结构文档

    作者:wide288 , 日期:2013-7-31 以前开发中,用 MYSQL 数据库,有个小程序 生成数据库结构文档.很方便,做为开发组的文档很有用. 现在开发中用到了 SQL SERVER 200 ...