发一个异步图片加载控件。网上也有大把的异步网络加载图片的控件,但是有一个问题,异步加载会造成列表中的图片混乱,因为列表的每一项的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. 数据结构与算法分析——C语言描述

    P1.1 选择问题,选择出第K大的数,并画出N为不同值的运行时间,K=N/2 毕业两年半,重写排序,感觉良好.代码使用冒泡排序,库函数clock计算大致运行时间. // P1_1.cpp : Defi ...

  2. Linux命令之hwclock - 查询和设置硬件时钟

    常用参数 -r, --show         读取并打印硬件时钟(read hardware clock and print result ) -s, --hctosys      将硬件时钟同步到 ...

  3. Delphi中WebBrowser拦截网页Alert对话框消息(转)

    interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, O ...

  4. 计算机体系结构-内存调优IPC OOMK

    man ipc [root@server1 proc]# man ipcIPC(2)                     Linux Programmer’s Manual             ...

  5. Qt 学习之路 :文件

    文件操作是应用程序必不可少的部分.Qt 作为一个通用开发库,提供了跨平台的文件操作能力.从本章开始,我们来了解下 Qt 的文件以及输入输出的功能,也就是 I/O 系统. Qt 通过QIODevice提 ...

  6. CentOS+Nginx+PHP+MySQL详细配置(图解)

    原文地址: http://www.jb51.net/article/26597.htm CentOS+Nginx+PHP+MySQL详细配置(带有图解),需要的朋友可以参考下.   一.安装MySQL ...

  7. [转] 函数编程之闭包漫谈(Closure)

    在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义 先:闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境).这个从字面上很难理解,特别对于一 ...

  8. 关于echarts绘图,主题的更换

    echarts主题进行更换步骤: 模块化单文件引入(推荐) 1.查看自己想要的主题  echarts官网 http://echarts.baidu.com/echarts2/doc/example/t ...

  9. Sql2008中使用DataTable作为存储过程的参数

    使用DataTable作为存储过程的参数   最近工作中写了几个存储过 程,需要向存储过程中传递字符串,因为SQL Server 2000中没有内置类似于 split 的函数,只好自己处理,将前台数据 ...

  10. Android Camera 流程梳理

    毕业已经快两年了,一直没有写博客的习惯,这是第一篇,以后要慢慢养成这个习惯.毕业之后一直在做相机,先简单的梳理下Android Camera的流程. Android Camera 是一个client/ ...