Android ListView异步加载数据库图片

需求:从数据库中得到图片的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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值