关于android应用OOM检查与bug修改

之前项目崩溃比较频繁,有的手机一直很正常,有的手机动不动就崩了,报的异常是OOM。特别是,在我新加入了一个多图选择框架后,点开多图选择崩溃的概率很高。那时候没有集成leakscanary,分享一下我解决问题的过程吧。

1.Android Studio的Motitors查看内存使用情况。可以看到有的手机内存占用80M左右很平稳,有的115M左右,逐渐飙升,最高达到128就崩了。有的手机能达到140左右,最高限度是256,所以不崩。这里讲一下手机的分配内存情况。手机给每个APP分配了一个最大内存,可以通过代码查看正常分配的内存和最大可分配内存。

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
activityManager.getMemoryClass();
activityManager.getLargeMemoryClass()

一般这两个值为128/256M或者256/512M,那么128M的机型还是比较容易OOM的,可以在manifest里开启最大内存分配:android:largeHeap=”true”。当然这种方式不建议,因为用户看到手机上可用内存变少、累积和许多垃圾后大量gc导致的卡顿会影响体验。
2.观察会发生OOM的手机,发现在splash页面,内存开销已经很大,跳转到主页以后,内存已经115以上,随便开个图片就OOM了。问题在于SplashActivity有内存泄漏的。经过查看,Splash用到的handler都有在onDestroy的时候removeCallback。但是既然还有泄漏,那就还是在handler上作文章。加了弱引用和静态Handler,具体代码如下:
private SkipHandler mHandler;
    private static class SkipHandler extends Handler {
        private WeakReference mWeakActivity;

        public SkipHandler(SplashActivity1 activity) {

            mWeakActivity = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            SplashActivity1 splashActivity1 = mWeakActivity.get();
            if (splashActivity1 == null) {
                return;
            }
            switch (msg.what) {
                case 0:
                    if (!splashActivity1.shouldFinish) {
                        if (NetUtils.mOutTime(splashActivity1)) {
                            if (MainApplication.getInstance().getUser() == null || MainApplication.getInstance().getUser().getUser() == null
                                    || MainApplication.getInstance().getUser().getUser().getType() == 0) {
                                splashActivity1.startActivity(new Intent(splashActivity1, IndexActivity.class));
                                splashActivity1.finish();
                                return;
                            }
                            if (MainApplication.getInstance().getUser().getUser().getType() == 2 && MainApplication.getInstance().getUser().getUser().getMonk().getIsPerfect() == 0) {
                                splashActivity1.startActivity(new Intent(splashActivity1, ApplyBuddhaActivity.class).putExtra("type", 0));
                                splashActivity1.finish();
                                return;
                            }
                            Intent intent = new Intent();
                            int currVersion = CommonUtils.getVersionCode(splashActivity1);
                            if (currVersion != -1 && splashActivity1.versionBean != null && splashActivity1.versionBean.getAndroidVersion() > currVersion) {
                                intent.putExtra("versionUpdate", splashActivity1.versionBean);
                            }
                            if (MainApplication.getInstance().getUser() == null || MainApplication.getInstance().getUser().getUser() == null) {
                                intent.setClass(splashActivity1, IndexActivity.class);
                            } else if (MainApplication.getInstance().getUser().getUser().getType() == 2) {
                                intent.setClass(splashActivity1, BuddhaMainActivity.class);
                            } else {
                                intent.setClass(splashActivity1, BelieverMainActivity.class);
                            }
                            splashActivity1.startActivity(intent);
                            splashActivity1.finish();
                        } else {
                            Intent intent = new Intent();
                            int currVersion = CommonUtils.getVersionCode(splashActivity1);
                            intent.setClass(splashActivity1, IndexActivity.class);
                            if (currVersion != -1 && splashActivity1.versionBean != null && splashActivity1.versionBean.getAndroidVersion() > currVersion) {
                                intent.putExtra("versionUpdate", splashActivity1.versionBean);
                            }
                            splashActivity1.startActivity(intent);
                            splashActivity1.finish();
                        }
                    }
                    break;
                //显示广告页面
                case 2:
                    if (TextUtils.isEmpty(mWeakActivity.get().adv_img)) {
                        //没有广告信息
                        splashActivity1.mHandler.sendEmptyMessageDelayed(0, 1 * 1000);
                    } else {
                        //存在广告页 显示4秒广告
                        if (splashActivity1.time == 0) {//广告显示结束
                            splashActivity1.mHandler.sendEmptyMessage(0);
                        } else {
                            if (splashActivity1.time == -1) {
                                splashActivity1.time = 4;
                                splashActivity1.showAdv();
                            }
                            splashActivity1.btn_skip.setText("跳过(" + splashActivity1.time + ")");
                            splashActivity1.time--;
                            splashActivity1.mHandler.sendEmptyMessageDelayed(2, 1 * 1000);
                        }
                    }
                    break;
            }
        }
    }

3.经过第2步以后再看内存使用情况,发现内存到达110多的时候就被回收了,OOM的概率大幅减小。然后还有一个BaseActivity里面遇到了环信的连线监听,这个也是一个内部类,也要写成静态的,加上弱引用。这里粘贴一部分代码。

private static class MyConnectionListener implements EMConnectionListener {
    private WeakReference<BaseActivity> mWeakActivity;

    public MyConnectionListener(BaseActivity activity) {
        mWeakActivity = new WeakReference<>(activity);
    }

    @Override
    public void onConnected() {
    }

    @Override
    public void onDisconnected(final int error) {
        final BaseActivity baseActivity = mWeakActivity.get();
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值