我们在开发中遇到了一个问题:制作本地图片选择功能时,加载图片可以选择fresco,自带缓存,加载迅速。但是在加载screenshot这个截图相册的时候,fresco加载异常缓慢。所以我们需要一个自己写一个相册加载类。另外如果不想用第三方开源库,这个类也是一个很好地选择。

我们一步一步来。
第一步:
简单粗暴的多线程加载


public void loadImage(final String path, final ImageView imageView) {
imageView.setTag(path);

// UI线程
if (mHandler == null) {
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
ImageView imageView = holder.imageView;
Bitmap bm = holder.bitmap;
String path = holder.path;
if (imageView.getTag().toString().equals(path)) {
imageView.setImageBitmap(bm);
}
holder.imageView = null;//否则随着手势滑动,内存不会释放,滑动一会儿直接就oom了
}
};
}


Runnable runnable = new Runnable() {
@Override
public void run() {

ImageSize imageSize = getImageViewWidth(imageView);

int reqWidth = imageSize.width;
int reqHeight = imageSize.height;

Bitmap bm = decodeSampledBitmapFromResource(path, reqWidth,
reqHeight);
// addBitmapToLruCache(path, bm);//将读取出的bitmap加入缓存
ImgBeanHolder holder = new ImgBeanHolder();
// holder.bitmap = getBitmapFromLruCache(path);
holder.bitmap = bm;
holder.imageView = imageView;
holder.path = path;
Message message = Message.obtain();
message.obj = holder;
// Log.e("TAG", "mHandler.sendMessage(message);");
mHandler.sendMessage(message);
// mPoolSemaphore.release();
}
};

new Thread(runnable).start();
}



这个时候,相册可以加载出来,但是滑动会非常卡顿。
运行程序,我们可以在monitor中看到,随着手势滑动,卡顿非常严重,CPU占用也很高。在ddms中看到瞬间多了30多个线程。。。。
并且没有缓存,滑出屏幕的所有元素,再滑动回来,都是空白,需要重新加载。


第二部:
加上lru缓存
下面为loadImage方法中主要的改动

Bitmap bm = getBitmapFromLruCache(path);
Log.d("cchen", path + " hit " + bm);

//从缓存取bitmap,判断是否命中
if (bm != null) {
ImgBeanHolder holder = new ImgBeanHolder();
holder.bitmap = bm;
holder.imageView = imageView;
holder.path = path;
Message message = Message.obtain();
message.obj = holder;
mHandler.sendMessage(message);

return;
}

//............
Bitmap bm = decodeSampledBitmapFromResource(path, reqWidth,
reqHeight);
[color=red]addBitmapToLruCache(path, bm)[/color];//将读取出的bitmap加入缓存
ImgBeanHolder holder = new ImgBeanHolder();
holder.bitmap = getBitmapFromLruCache(path);
// holder.bitmap = bm;
holder.imageView = imageView;


//............


加上LRU后,第一次加载的速度差不多。但是来回滑动后,缓存会命中很多,这样滑动一屏,新建的线程只有原来的一半15个,而且滑动回来后,很多图片也还在显示,不需要重新加载。卡顿减轻了很多但仍然有。
并且加载速度不够理想。

第三步:

土逼啃蹄牛
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐