Android 开发中经常会遇到处理图片的加载问题,如果处理不好会影响到整个app的用户体验,因此Android中通过开启一个异步线程去加载图片,用来防止UI线程的阻塞。
ListView是Android开发中最长用到的控件,其最长遇到的问题就是图文混排中图片的处理问题,内存溢出问题,而解决这一问的方式就是对网络加载加来的图片进行裁剪及缓存处理,从而增加Listview的使用流畅度。
下面开始相关内容的处理
- 缓存处理这里以LruCache为例:
lrucache 初始化方式:
//获取到系统当前运行最大内存
private final int maxMemory = (int) Runtime.getRuntime().maxMemory();
//用最大运行内存的1/8用来缓存当前图片
private final int cacheSize = maxMemory/8;
//初始化lrucache
private LruCache<String, Bitmap> mLruCache = new LruCache<String, Bitmap>(cacheSize){
protected int sizeOf(String key, Bitmap value) {
//将bitmap换算成kB
return value.getRowBytes()*value.getHeight()/1024;
}
};
- Lrucache 的存储方式是以键值对的方式
lruCache.put(key, value);
- Lrucache 的读取方式:
lruCache.get(key);
- 首先要使用ListView必须要创建适配器
//自定义一个适配器,如下MyAdapter 继承BaseAdapter,实现其相关方法
public class MyAdapter extends BaseAdapter {
private Context mContext;
//布局填充器
private LayoutInflater inflater;
//要显示的数据内容
private List<String> datas ;
//获取到系统当前运行最大内存
private final int maxMemory = (int) Runtime.getRuntime().maxMemory();
//用最大运行内存的1/8用来缓存当前图片
private final int cacheSize = maxMemory/8;
//初始化lrucache
private LruCache<String, Bitmap> mLruCache = new LruCache<String, Bitmap>(cacheSize){
protected int sizeOf(String key, Bitmap value) {
//将bitmap换算成kB
return value.getRowBytes()*value.getHeight()/1024;
}
};
//适配器构造函数
public MyAdapter(Context mContext, List<String> datas) {
super();
this.mContext = mContext;
this.datas = datas;
inflater = LayoutInflater.from(mContext);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return datas.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return datas.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
//这个方法就是将数据内容填充到ListView的每个Item中的方法
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder mHolder = null;
//这里的的逻辑是当convertView为空时,就添加一个新的View,同时与ViewHolder 绑定在一起
if(convertView == null){
convertView = inflater.inflate(R.layout.listview_item_layout, parent, false);
mHolder = new ViewHolder();
mHolder.mtv = (TextView) convertView.findViewById(R.id.textView1);
mHolder.miv = (ImageView) convertView.findViewById(R.id.imageView1);
//给convertView,设置一个Tag用来下次利用时重复利用
convertView.setTag(mHolder);
}else{
//当不为空时,直接获取到mHolder,不用重新去添加,提高了速度
mHolder = (ViewHolder) convertView.getTag();
}
//将文本数据信息展示
mHolder.mtv.setText(datas.get(position));
//图片加载需要异步处理,避免影响主线程,
loadBitmap(datas.get(position), mHolder.miv);
return convertView;
}
//这里添加一个ViewHolder ,其目的是用来重复利用之前加载过的item,使其不用重新findviewbyid()寻找对应的控件,从而提高了item的利用率
private class ViewHolder{
private TextView mtv;
private ImageView miv;
}
//异步加载 图片,用来加载网络上的图片,同时进行图片的缓存处理
private void loadBitmap(String urlStr,ImageView imageView){
MyImageLoaderAsync asyncLoader = new MyImageLoaderAsync(imageView, mLruCache);
Bitmap bitmap = asyncLoader.getBitmapFromMemoryCache(urlStr);
if(bitmap != null){
imageView.setImageBitmap(bitmap);
}else{
//如果图片还没有加载,则先找一个图片替代,当加载完成后在显示出来
imageView.setImageResource(R.drawable.ic_launcher);
asyncLoader.execute(urlStr);
}
}
}
- 接下来是写一个图片异步加载的类MyImageLoaderAsync ,用来处理图片异步网络加载,同时对新加载下来的图片进行缓存处理
public class MyImageLoaderAsync extends AsyncTask<String, Integer, Bitmap>{
private ImageView image;
//本地缓存
private LruCache<String, Bitmap> lruCache;
/**
* 构造方法,需要把ImageView控件和LruCache 对象传进来
* @param image 加载图片到此 {@code}ImageView
* @param lruCache 缓存图片的对象
*/
public MyImageLoaderAsync(ImageView image, LruCache<String, Bitmap> lruCache) {
super();
this.image = image;
this.lruCache = lruCache;
}
@Override
protected Bitmap doInBackground(String... params) {
//此处内容为 通过网络下载图片,并返回Bitmap
Bitmap bitmap = null;
//方法区,网络加载功能
、、、、
//加载图片完成后将图片缓存到本地
addBitmapToMemoryCache(params[0], bitmap);
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
//super.onPostExecute(result);
image.setImageBitmap(result);
}
//添加新加载的图片到缓存中
private void addBitmapToMemoryCache(String key,Bitmap bitmap){
if(getBitmapFromMemoryCache(key) == null){
lruCache.put(key, bitmap);
}
}
//调用Lrucache的get方法从内存缓存中查询图片并返回
public Bitmap getBitmapFromMemoryCache(String key){
return lruCache.get(key);
}
}