ANR:Application Not Responding
使用Android手机有时候会遇到系统弹框“应用程序无响应”,这是因为APP在前台或者后台主线程中执行的时间太长,没有响应用户的操作。

1、ANR条件
系统ActivityManager和WindowManager会监控应用,如下三种条件下会产生ANR:
①Activity:前台在5s内无法响应输入事件(触摸、按键);定义在:ActivityTaskManagerService
// How long we wait until we timeout on key dispatching.
public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;
// How long we wait until we timeout on key dispatching during instrumentation.
static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000;
// How long we permit background activity starts after an activity in the process started or finished.
static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000;②BroadcastReceiver:前台广播10s,后台广播60s无法响应;定义在:ActivityManagerService
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_FG_TIMEOUT = 10*1000;
static final int BROADCAST_BG_TIMEOUT = 60*1000;③Service:前台服务20s,后台服务200s未响应;定义在:ActiveServices
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;
// How long we wait for a service to finish executing.
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;
// How long the startForegroundService() grace period is to get around to
// calling startForeground() before we ANR + stop it.
static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000;2、ANR分析
当应用出现ANR,这个时候就该好好通过trance分析分析到底应用程序主线程哪里进行了耗时操作,需要移到子线程中处理。打开开发者选项中的ANR开关,直观的看到系统提示ANR弹框。

2.1、示例
想造一个ANR,很简单,在前台主线程Sleep超过5s即可。
@Override
protected void onCreate(Bundle savedInstanceState) {
...
try {
Thread.sleep(500000);
} catch (Exception e) {
Log.d(TAG, e.toString());
}
}运行打开应用直接黑屏,按Home键都没有作用。如果手机上遇到这种应用建议直接卸载。
2.2、日志分析
应用程序产生ANR都会在/data/anr/目录下生成一个日志,比如:/data/anr/anr_2020-07-27-23-06-18-920。用adb命令pull出来分析,当然还有其它途径获取相关日志。(用的华为手机演示,竟然要root才能把anr日志pull出来)
adb pull data/anr .2.3、trace分析
拿不到日志或者通过日志还需要进一步分析,产生ANR的原因。使用DDMS工具,抓取trace获取执行的时序图:
可以看到main一直卡住,直到最后才能执行,UI线程超时后就会发生ANR,查看耗时的方法:
3、避免ANR
避免ANR:不要在主线程执行耗时操作,主线程只执行UI操作。其它所有的数据、网络、文件读写都在子线程中(最好用线程池统一管理线程)。
①主线程只操作UI
②耗时(I/O、网络)操作全部放到子线程
③频繁的GC也会导致ANR,需要优化内存
④即将发生OOM前也会可能产生ANR,因为频繁的GC
推荐资料:



