您的位置:首页 > 移动开发 > Android开发

Android ListView异步加载数据库图片

2016-01-28 19:37 453 查看
需求:从数据库中得到图片的byte数据,编码成png图片,显示到ListView上
这里最大一个问题就是ListView滑动卡的问题,要解决卡,就需要用到异步加载数据库的图片;

原创博客,转载注明出处:http://blog.csdn.net/deng0zhaotai/article/details/50596332



程序第一次启动时会把assets中的数据库压缩文件复制到/data/data/packageName.../databases/目录下,这里使用的是网上找的一个工具类,详细代码可以在下面的链接下载,异步操作主要是在Adapter的getView()函数中处理,如果已经添加到缓存就直接取,否则会开启task去加载,下面看下ImageAdapter的详细代码,都有添加注释,应该不难理解

package com.dzt.listviewshow;

import java.util.List;

import com.dzt.listviewshow.AsyncImageLoader.OnLoadFinishListener;
import com.dzt.listviewshow.utils.LogUtils;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ImageAdapter extends BaseAdapter {

private Context context;
private List<CarClass> carClass;
private LayoutInflater mInflater;
private LruCache<String, Bitmap> mMemoryCache;

public ImageAdapter(Context context, List<CarClass> carClass) {
this.context = context;
this.carClass = carClass;
mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

// LruCache通过构造函数传入缓存值,以KB为单位。
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// 使用最大可用内存值的1/8作为缓存的大小。
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// 重写此方法来衡量每张图片的大小,默认返回图片数量。
return bitmap.getByteCount() / 1024;
}
};
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return carClass.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return carClass.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
// 1获取item,再得到控件
// 2 获取数据
// 3绑定数据到item
ViewHolder hodler = null;
CarClass cc = carClass.get(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item, null);
hodler = new ViewHolder();
hodler.tvView = (TextView) convertView.findViewById(R.id.tv_title);
hodler.ivView = (ImageView) convertView.findViewById(R.id.iv_img);
convertView.setTag(hodler);

} else {
hodler = (ViewHolder) convertView.getTag();
}
hodler.ivView.setTag(cc.index);
final Bitmap bitmap = getBitmapFromMemCache("" + cc.index);
if (bitmap == null) {
LogUtils.i("getView-----bitmap == null");
hodler.ivView.setImageResource(R.drawable.carback);
// 异步的加载图片 (线程池 + Handler ) ---> AsyncTask
asyncloadImage(hodler.ivView, cc);
} else {
LogUtils.i("getView-----bitmap != null");
hodler.ivView.setImageBitmap(bitmap);
}

hodler.tvView.setText("第 " + position + " 个 " + cc.carClass);

return convertView;
}

private void asyncloadImage(ImageView iv_header, CarClass cc) {
AsyncImageLoader task = new AsyncImageLoader(context, iv_header,
cc.index, new LoadFinish());
task.execute(cc.bitmap);
}

class ViewHolder {
ImageView ivView;
TextView tvView;
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}

public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}

class LoadFinish implements OnLoadFinishListener {

@Override
public void onLoadFinish(Bitmap bitmap, int index) {
// TODO Auto-generated method stub
LogUtils.i("onLoadFinish-----index = " + index);
addBitmapToMemoryCache(String.valueOf(index), bitmap);
}
}
}
为了防止滑动过快时错位显示,需要在getview函数为ImageView加上hodler.ivView.setTag(cc.index);,在异步加载时根据Tag是否显示

package com.dzt.listviewshow;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

public class AsyncImageLoader extends AsyncTask<byte[], Void, Bitmap> {

private Context mContext;
private ImageView image;
private int mIndex;
private OnLoadFinishListener mListener;

/**
* 构造方法,需要把ImageView控件和LruCache 对象传进来
*
* @param image
*            加载图片到此 {@code}TextView
* @param lruCache
*            缓存图片的对象
*/
public AsyncImageLoader(Context context, ImageView image, int index,
OnLoadFinishListener listener) {
mContext = context;
this.image = image;
mIndex = index;
mListener = listener;
}

@Override
protected Bitmap doInBackground(byte[]... params) {
// TODO Auto-generated method stub

return getBitmap(params[0]);
}

@Override
protected void onPostExecute(Bitmap bitmap) {
int inx = (int) image.getTag();
if (mIndex == inx) {
image.setImageBitmap(bitmap);
if (mListener != null) {
mListener.onLoadFinish(bitmap, mIndex);
}
}
}

// 解析图片
private Bitmap getBitmap(byte[] icon) {
return BitmapFactory.decodeByteArray(icon, 0, icon.length);
}

interface OnLoadFinishListener {
public void onLoadFinish(Bitmap bitmap, int index);
}
}


关键代码:

int inx = (int) image.getTag();

if (mIndex == inx) {

image.setImageBitmap(bitmap);

if (mListener != null) {

mListener.onLoadFinish(bitmap, mIndex);

}

}

本文可以学习到异步加载图片、防止item显示错位、图片缓存、解压压缩文件

代码下载链接:http://pan.baidu.com/s/1qXuwilu
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息