APP性能优化系列:ViewPager加载大图出现OOM优化

  最近公司的app有一些医生反馈说:预览患者发送的图片加载的特别慢,并且经常加载不出来。

  仔细分析这个问题的由来,之前客户端预览大图页加载图片设置的像素数是1024*720,即一张图片占用的内存为:1024*720*2=1.4M(大概).大图预览页面采用的是viewpager,viewpager默认占用的内存为3*1.4M,不易出现OOM。

  后来做了一次大图预览调整,最终的解决方案是调整预览大图页加载图片的像素改为:1024*2*720*2,即一张图片占用的内存为:1024*2*720*2*2=5.12M(大概), 大图预览页面采用的是viewpager,viewpager默认占用的内存为3*5.12M,易出现OOM。

  一般情况下Android手机为每个应用分配的内存大概是64M。而一个大图预览就占用了15M左右,更别说如果viewpager中有十几张大图,如果bitmap没有得到及时的释放,就是十几*5.12M了。OOM就更易出现了。

目前的思考解决方案如下:

解决步骤1:在viewpager destroyitem的时候及时释放bitmap
来自网络的一段代码:

BitmapDrawable bitmapDrawable = (BitmapDrawable) imageView.getDrawable();
            if (bitmapDrawable != null) {
                Bitmap bm = bitmapDrawable.getBitmap();
                if (bm!=null && !bm.isRecycled()) {
                    Log.d("...desimg..", "被回收了" + bm.getByteCount());
                    imageView.setImageResource(0);
                    bm.recycle();
                }
            }


验证日志:

08-11 20:40:52.660 13100-13100/com.haodf.android.doctor D/...desfrag..: 我执行了
08-11 20:40:52.660 13100-13100/com.haodf.android.doctor D/...desimg..: 我执行了
08-11 20:40:52.660 13100-13100/com.haodf.android.doctor D/...desimg..: 被回收了2646720  2.5m
08-11 20:40:55.140 13100-13100/com.haodf.android.doctor D/...desfrag..: 我执行了
08-11 20:40:55.140 13100-13100/com.haodf.android.doctor D/...desimg..: 我执行了
08-11 20:40:55.140 13100-13100/com.haodf.android.doctor D/...desimg..: 被回收了2764800
08-11 20:40:57.360 13100-13100/com.haodf.android.doctor D/...desfrag..: 我执行了
08-11 20:40:57.360 13100-13100/com.haodf.android.doctor D/...desimg..: 我执行了
08-11 20:40:57.360 13100-13100/com.haodf.android.doctor D/...desimg..: 被回收了4991040 4.7m
有效果。

解决步骤2:让系统为应用分配更多的内存
  目前APP对图片的质量要求越来越高,已经具备引入largeHeap属性的条件。如果设置了这个属性,这样就能增加系统为当前app分配的内存了,甚至到100M以上。可以明显减少OOM的问题。

解决步骤3:图片局部加载
  参考了一些开源的相册类应用和壁纸类应用,发现他们使用了局部加载的技术。这种技术会先将图片下载到本地,然后去加载,只加载当前可视区域,在手指拖动的时候再去加载另外的区域,可以彻底解决oom的问题,测验在viewpager的情况下加载10000*10000分辨率的图片毫无压力。

  这块有一个非常好的开源第三方可以参考:SubsamplingScaleImageView。这个控件支持局部加载,类似qq相册的大图预览效果。

源码分析如下: 
http://www.cnblogs.com/idealgrass/p/4429798.html

使用示例如下:

/**
 * Created by niehongtao on 16/8/12.
 */
public class BigImgTestActivity extends BaseActivity {
    @InjectView(R.id.imageView)
    SubsamplingScaleImageView imageView;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_bigimg;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        super.mLoadingDialog.hideLoading();
        final String testUrl = "http://n2.hdfimg.com/g9/M00/1E/B4/uoYBAFepon-AKjTRANKobLODE_M932.jpg";
        final File downDir = Environment.getExternalStorageDirectory();
        //使用Glide下载图片,保存到本地
        Glide.with(this)
                .load(testUrl)
                .asBitmap()
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                        File file = new File(downDir, "m_1385635534691.jpg");
                        if (!file.exists()) {
                            try {
                                file.createNewFile();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        FileOutputStream fout = null;
                        try {
                            //保存图片
                            fout = new FileOutputStream(file);
                            resource.compress(Bitmap.CompressFormat.JPEG, 100, fout);
                            // 将保存的地址给SubsamplingScaleImageView,这里注意设置ImageViewState
                            imageView.setImage(ImageSource.uri(file.getAbsolutePath()));
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                if (fout != null) fout.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
    }

    @Override
    protected void initView() {

    }

    @Override
    protected void initData() {

    }
}


相信通过以上三步可以完全杜绝预览大图时的OOM的问题了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值