背景
由于是初次接触Android开发,老师分配给我的是项目中相册开发部分。
思路
项目要求是需要从大疆无人机上获取到图片视频,因为调试麻烦,所以先获取Pad上的媒体文件进行模拟。
当时的想法是获取到文件后,在PhotoPreActivity中直接把全部文件加载到ImagePagerAdapter中。
List<ImageView> mViews = new ArrayList<>();
int size = mDatas.size();
for (int i = 0; i < size; i++) {
ImageView view = new ImageView(this);
mViews.add(view);
}
mImagePagerAdapter = new ImagePagerAdapter(this, mViews);
bigImgVp.setAdapter(mImagePagerAdapter);
测试时,在进行大图浏览的过程中,程序开始卡顿然后突然崩溃,使用AS的Profile发现在进行浏览时,内存一直在不停地增加。
解决方案
一、使用Glide与PhotoView
导入Glide与PhotoView的依赖
implementation 'com.github.chrisbanes.photoview:library:+'
implementation 'com.github.bumptech.glide:glide:4.5.0'
使用缩略图来提高加载速度和降低内存占用。根据控件大小对图片进行裁剪,减少不必要内存浪费。
RequestOptions myOptions = new RequestOptions()
.fitCenter()
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(context)
.load(new File(path[section][position]))
.transition(withCrossFade()) // .crossFade()()
.apply(centerCropTransform()) // .centerCrop()
.apply(myOptions)
.thumbnail(0.5f)
.into(viewHolder.thumb);
Glide.with(mContext)
.load(photo.getPath())
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
photoView.setImageDrawable(resource);
}
});
虽然相比之前效果好点了,然而在浏览四十张图片后,内存开始暴涨,随后程序崩溃。
二、对ViewPager进行改进
Viewpager使用起来就是我们通过创建Adapter给它填充多个View,左右滑动时,切换不同的View。因为随着图片浏览的进行,ViewPager加载越来越多图片的时候就会OOM。
- 在Viewpager里做资源回收;
- 保证Viewpager加载的mViews存储的图片为4个,分别是当前页,上一页,下一页以及下下一页。
在ImagePagerAdapter中
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (object instanceof PhotoView) {
PhotoView view = (PhotoView) object;
view.setImageDrawable(null);
viewList.add(view);
container.removeView((View) view);
}
}
private void createImageViews() {
for (int i = 0; i < 4; i++) {
PhotoView imageView = new PhotoView(mContext);
imageView.setAdjustViewBounds(true);
viewList.add(imageView);
}
}
经过这两次改进后,到目前为止还未出现过OOM。
附上GitHub GalleryDJI