ListView在使用holder的过程中会减少内存的使用,但是另一方面,在listview的每一个item的数据都很多时,特别是加载网络图片的时候,有可能会出现图片加载过慢,图片加载错位问题,尝试过很多方法,终于找到了一种还不错的方法。
第一步:
在holder的基础上加入reset方法:
class ImgHolder {
private TextView tv_number;
private TextView tv_name;
private CircleImageView cimg_head;
}
private void resetImgHolder(ImgHolder imgHolder) {
imgHolder.tv_name.setText(null);
imgHolder.tv_number.setText(null);
imgHolder.cimg_head.setImageDrawable(null);
}
在每次调用完getTag方法后调用一下这个方法
if (null == convertView) {
convertView = LayoutInflater.from(context).inflate(
R.layout.item_imglist, null);
imgHolder = new ImgHolder();
imgHolder.cimg_head = (CircleImageView) convertView
.findViewById(R.id.cimg_head);
imgHolder.tv_name = (TextView) convertView
.findViewById(R.id.tv_name);
imgHolder.tv_number = (TextView) convertView
.findViewById(R.id.tv_number);
convertView.setTag(imgHolder);
} else {
imgHolder = (ImgHolder) convertView.getTag();
resetImgHolder(imgHolder);
}
第二步:
判断list中是否有值,如果没有值的话也要去设置值
if(null!=imgList.get(position).getImgUrl()){
BitmapUtilsHelp
.getImage(context, R.drawable.defalut_user_icon)
.display(imgHolder.cimg_head, imgList.get(position).getImgUrl());
}else{
imgHolder.cimg_head.setImageResource(R.drawable.defalut_user_icon);
}
第三步:
也是最关键的一步 加入缓存
package com.example.imageholder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Comparator;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.StatFs;
import android.util.Base64;
import android.util.Log;
/**
* TODO:图片缓存:本地文件缓存类
* @version 1.0, 2013-11-18/下午4:22:38
*/
public class ImageFileCache
{
// 图片缓存目录
public static final String CACHDIR = ".mtc/cache/";
public static final String School_Cache = ".mfc_school";
private static final String WHOLESALE_CONV = ".png";
private static final int MB = 1024 * 1024;
private static final int CACHE_SIZE = 50;
private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 64;
public ImageFileCache()
{
// 清理文件缓存
removeCache(getDirectory());
}
/** 从缓存中获取图片 **/
public Bitmap getImage(final String url)
{
final String path = getDirectory() + "/" + convertUrlToFileName(url);
File file = new File(path);
if (file.exists())
{
Bitmap bmp = BitmapFactory.decodeFile(path);
if (bmp == null)
{
file.delete();
}
else
{
updateFileTime(path);
return bmp;
}
}
return null;
}
/** 将图片存入文件缓存 **/
public void saveBitmap(Bitmap bm, String url)
{
if (bm == null)
{
return;
}
// 判断sdcard上的空间
if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd())
{
// SD空间不足
return;
}
String filename = convertUrlToFileName(url);
String dir = getDirectory();
File dirFile = new File(dir);
if (!dirFile.exists())
dirFile.mkdirs();
File file = new File(dir + "/" + filename);
try
{
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
}
catch(FileNotFoundException e)
{
Log.e("ImageFileCache", "FileNotFoundException");
}
catch(IOException e)
{
Log.e("ImageFileCache", "IOException");
}
}
/**
* 计算存储目录下的文件大小,
* 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
* 那么删除20%最近没有被使用的文件
*/
private boolean removeCache(String dirPath)
{
File dir = new File(dirPath);
File[] files = dir.listFiles();
if (files == null)
{
return true;
}
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED))
{
return false;
}
int dirSize = 0;
for (int i = 0; i < files.length; i++)
{
if (files[i].getName().contains(WHOLESALE_CONV))
{
dirSize += files[i].length();
}
}
if (dirSize > CACHE_SIZE * MB
|| FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd())
{
int removeFactor = (int) ((0.2 * files.length) + 1);
Arrays.sort(files, new FileLastModifSort());
for (int i = 0; i < removeFactor; i++)
{
if (files[i].getName().contains(WHOLESALE_CONV))
{
files[i].delete();
}
}
}
if (freeSpaceOnSd() <= CACHE_SIZE)
{
return false;
}
return true;
}
/** 修改文件的最后修改时间 **/
public void updateFileTime(String path)
{
File file = new File(path);
long newModifiedTime = System.currentTimeMillis();
file.setLastModified(newModifiedTime);
}
/** 计算sdcard上的剩余空间 **/
private int freeSpaceOnSd()
{
StatFs stat = new StatFs(Environment.getExternalStorageDirectory()
.getPath());
double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat
.getBlockSize()) / MB;
return (int) sdFreeMB;
}
/** 将url转成文件名 **/
private String convertUrlToFileName(String url)
{
String[] strs = url.split("/");
String filename = base64Encode(strs[strs.length - 1]).trim();
return filename + WHOLESALE_CONV;
}
/** 获得缓存目录 **/
public static String getDirectory()
{
String dir = getSDPath() + File.separator + CACHDIR;
return dir;
}
public static String getSchoolDirectory()
{
String dir = getSDPath() + File.separator + School_Cache;
return dir;
}
public static String getPicDirectory()
{
String dir = getSDPath() + File.separator + "mzone/pic/";
return dir;
}
/** 取SD卡路径 **/
private static String getSDPath()
{
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
if (sdCardExist)
{
sdDir = Environment.getExternalStorageDirectory(); // 获取根目录
}
if (sdDir != null)
{
return sdDir.toString();
}
else
{
return "";
}
}
/**
* 根据文件的最后修改时间进行排序
*/
private class FileLastModifSort implements Comparator
{
public int compare(File arg0, File arg1)
{
if (arg0.lastModified() > arg1.lastModified())
{
return 1;
}
else if (arg0.lastModified() == arg1.lastModified())
{
return 0;
}
else
{
return -1;
}
}
}
/**
* 检查该网络图片是否存在
*/
public boolean checkImageExist(String url){
String filename = convertUrlToFileName(url);
String dir = getDirectory();
File dirFile = new File(dir);
if (!dirFile.exists())
return false;
File file = new File(dir + "/" + filename);
if(!file.exists()){
return false;
}
return true;
}
public static String base64Encode(String str)
{
return Base64.encodeToString(str.getBytes(), Base64.DEFAULT);
}
public static String base64Decode(String pContent)
{
byte b[] = Base64.decode(pContent, Base64.DEFAULT);
return new String(b);
}
}
当然还有一些自己的方法,大家可以去下载我写的demo查看
网址 http://download.csdn.net/detail/qq_29986595/9532781