发一个异步图片加载控件。网上也有大把的异步网络加载图片的控件,但是有一个问题,异步加载会造成列表中的图片混乱,因为列表的每一项的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. [zz]android的logcat详细用法

    Android日志系统提供了记录和查看系统调试信息的功能.日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过 logcat 命令来查看和使用.      一.使用logcat命令的目的: ...

  2. 关于字符编码精简介绍 ANSI GB2312 UTF8 UNICODE

  3. hdu 1242 dfs/bfs

    Problem Description Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is ...

  4. [kuangbin带你飞]专题十 匹配问题 二分图多重匹配

    二分图的多重匹配问题不同于普通的最大匹配中的"每个点只能有最多一条边" 而是"每个点连接的边数不超过自己的限定数量" 最大匹配所解决的问题一般是"每个 ...

  5. 【转】jQuery列表拖动排列-jquery list dragsort插件参数和使用方法

    转自:http://www.itokit.com/2014/0820/75058.html 我们在编辑页面元素排序的时候,我推荐使用jquery插件:dragsort. dragsort官网地址:ht ...

  6. Python安装scipy

    1.下载numpy+mkl 下载链接:http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy 2.下载scipy 下载链接:http://www.lfd.uc ...

  7. C#自定义泛型类绑定ComboBox控件

    C# WinForm ComboBox 自定义数据项 (ComboBoxItem ) WinForm下的ComboBox默认是以多行文本来设定显示列表的, 这通常不符合大家日常的应用, 因为大家日常应 ...

  8. Linux下Postfix的配置和使用

    Postfix为何物,详见:http://zh.wikipedia.org/wiki/Postfix 0.关于Postfix postfix的产生是为了替代传统的sendmail.相较于sendmai ...

  9. SICP 习题 (1.8) 解题总结

    SICP 习题1.8需要我们做的是按照牛顿法求平方根的方法做一个求立方根的过程. 所以说书中讲牛顿法求平方根的内容还是要好好理解,不然后面这几道题做起来就比较困难. 反过来,如果理解了牛顿法求平方根的 ...

  10. [Flux] 2. Overview and Dispatchers

    Flux has four major components: Stores, Dispatchers, Views, and Actions. These components interact l ...