ANR产生原因:

  • 只有当应用程序的UI线程响应超时才会引起ANR,超时原因:
  • 当前事件没有机会得到处理
  • 当前的事件正在处理,但是由于耗时太长没能及时完成
  • 引发ANR的原因;
  • View的按键事件或者触摸事件在5s内无法得到响应
  • BroadcastReceiver的onReceive()函数在10s内没有得到处理
  • Service各个生米周期函数在20s内没有得到处理

典型的ANR场景分析:

  • 应用程序UI线程存在耗时任务,例如在UI线程中进行网络请求(Android4.0之前,4.0之后会报错),数据库操作或者文件操作等,可能会导致UI线程无法及时处理用户的输入。
  • UI线程等待子线程释放某个锁,从而用户无法输入
  • 耗动画可能需要大量的计算工作,可能导致CPU负载过重

ANR的避免和检测:

StrictMode: 是AndroidSDk提供的一个用来检测代码中是否存在违规操作的工具类,它主要检测两大类问题:
  • 线程策略ThreadPolicy
  • detectCustomSlowCalls:检测自定义耗时操作
  • detectDiskReads:检测是否存在磁盘读取操作
  • detectDiskWrites:检测是否存在磁盘写入操作
  • detectNetwork:检测是否存在网络操作
  • 虚拟机策略VmPolicy
  • detectActivityLeaks:检测是否存在Activity泄漏
  • detectLeakedClosableObjects:检测是否存在未关闭的Closable对象泄漏
  • detectLeakedSqlLiteObjects:检测是否存在Sqlite的对象泄漏
  • setClassInstanceLimit:检测类实例个数是否超过限制
  • StrictMode的使用: 在应用初始化的地方Application或者MainActivity类的onCreate方法中执行:
if(BuildConfig.DEBUG){
//开启线程策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
//开启虚拟机模式
StrictMode.setVmPolicy(new VmPolicy.Builder().detectAll().penaltyLog().build());
}
super.onCreate(savedInstanceState);
​BlockCanary​​:是一个非侵入式的性能监控函数库,用法和LeakCanary类似,BlockCanary主要用来监控应用主线程的卡顿,基本原理就是利用主线程的消息队列处理机制,通过对比消息分发开始和结束的时间点来判断是否超过设定的时间,如果是,则判断主线程卡顿,下面是使用的方法
  • 首先在app下的build.gradle中的dependencies中添加如下代码:
dependencies {
...
implementation 'com.github.markzhai:blockcanary-android:1.5.0'
// 仅在debug包启用BlockCanary进行卡顿监控和提示的话,可以这么用
debugCompile 'com.github.markzhai:blockcanary-android:1.5.0'
releaseCompile 'com.github.markzhai:blockcanary-no-op:1.5.0'
}
  • 在Application中:
public class DemoApplication extends Application {
@Override
public void onCreate() {
// 在主进程初始化调用哈
BlockCanary.install(this, new AppBlockCanaryContext()).start();
}
}