ANR问题分类
对于ANR发生原理及Trace文件产生机制不清晰的可以先看这几篇文章
ANR系列文章
IdleHandler你会用吗?记一次IdleHandler使用误区,导致ANR
为了方便后面介绍,我这里根据遇到case,可以将卡顿大致分为以下几种类:
- 主线程IO
- 高频次Binder调用
- Webview初始化
- 主线程等待低优先级
- onTrimMemory
- 低效并发
- 耗时方法
至于分类大可不必过于较真,因为即使是对一类问题,解决方式也并不一定相同,下面问题介绍也并不是按照上面的顺序来。
1.主线程IO
在主线程中加载dex文件,容易造成卡顿;解决方式,建议dex加载最好放到子线程。类似的还有加载so文件:
2.SharedPreferences apply()方法导致
关于SharedPreferences导致的ANR问题,建议大家直接看这篇文章的介绍SharedPreferences ANR问题分析 & Android8.0的优化,当然也并不能完全解决此类问题。另外还有一种方案就是直接替换SharedPreferences为腾讯开源的MMKV
3.JSON反序列化
主线程耗时方法,这类问题首先要考虑是否能进行方法内部优化,并不是光考虑该使用哪种高效的反序列化框架,因为再高效的方式也高效不过不做任何事情。这里题主配合同事经过分析后发现这里其实并不需要反序列化,可以直接传递json。当然我们还可以更简单的来处理,将反序列化工作放进子线程去工作。
4.初始化Webview
Webview初始化,项目抓取到了很多Webview相关的ANR(x5webview和webview都有,这里以x5webview
举例)。尤其是Webview初始化时,当然Webview问题比较多,也有不少解决方案。比如独立进程;而题主的项目里是通过Webview预加载的方式来减少使用时初始化耗时,当然预加载的方案还需要关注内存占用问题。关于内存相关的问题,后面会有专题介绍。
另外由于项目中接入了穿山甲广告SDK,也抓取到了很多穿山甲Webview初始化的ANR:
5.IdleHandler使用不当问题
主线程耗时方法,关于IdleHandler带来问题,可以看我之前的文章 IdleHandler你会用吗?记一次IdleHandler使用误区,导致ANR
6.onTrimMemory导致ANR
7.ConnectivityManager.getActiveNetworkInfo
高频Binder调用,这种跨进程调用,不确定性较强,稍有不慎就会成为耗时方法。由于项目接口公共参数含有网络状态,每次网络请求都会重新获取网络状态。解决方式使用NetWorkChangeReceiver监听网络状态变化,保存在内存中,替换通过ConnectivityManager来获取。
类似的还有ActivityManagerProxy.getRunningAppProcesses
最后还有很多情况这里没有列举出来,我这里只是将遇到几个典型问题拿出来分享,欢迎大家补充和讨论。另外还有一个大家可能比较感兴趣的问题,如何收集线上ANR,这里又要区分Android8.0以上的版本与之前版本的差异,这里提醒一句,如果有同学项目使用免费版bugly作为稳定性收集平台,那你基本上看不到8.0以上版本的ANR问题,这块的方案后面会择机和大家分享。
感谢各位品读,欢迎留言讨论。