banner
NEWS LETTER

Android ANR(应用无响应)

Scroll down

前言

在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。

ANR原因

1
Android系统中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会检测App的响应时间,如果App在特定时间无法相应屏幕触摸或键盘输入时间,或者特定事件没有处理完毕,就会出现ANR。
ANR问题本质是一个性能问题。ANR机制实际上对应用程序主线程的限制,要求主线程在限定的时间内处理完一些最常见的操作(启动服务、处理广播、处理输入), 如果处理超时,则认为主线程已经失去了响应其他操作的能力。主线程中的耗时操作,譬如密集CPU运算、大量IO、复杂界面布局等,都会降低应用程序的响应能力。

ANR出现场景

发生ANR时会调用AppNotRespondingDialog.show()方法弹出对话框提示用户,该对话框的依次调用关系如下图所示:

AppErrors.appNotResponding(),该方法是最终弹出ANR对话框的唯一入口,调用该方法的场景才会有ANR提示,也可以认为在主线程中执行无论再耗时的任务,只要最终不调用该方法,都不会有ANR提示,也不会有ANR相关日志及报告;通过调用关系可以看出哪些场景会导致ANR,有以下四种场景:
  • InputDispatching Timeout:5秒内无法响应屏幕触摸事件或键盘输入事件。
  • BroadcastQueue Timeout :在执行前台广播(BroadcastReceiver)的onReceive()函数时10秒没有处理完成,后台为60秒。
  • Service Timeout :前台服务20秒内,后台服务在200秒内没有执行完毕。
  • ContentProvider Timeout :ContentProvider的publish在10s内没进行完。

ANR原因

  • 主线程慢代码
  • 主线程IO
  • 锁竞争
  • 死锁

如何避免ANR

  1. UI线程尽量只做跟UI相关的工作;
  2. 耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理;
  3. 尽量用Handler来处理UI thread和别的thread之间的交互;
  4. 实在绕不开主线程,可以尝试通过Handler延迟加载;
  5. 广播中如果有耗时操作,建议放在IntentService中去执行,或者通过goAsync() + HandlerThread分发执行。

分析ANR的重点

  1. cpu占用率方面:
    可以通过分析各进程的CPU时间占用率,来判断是否为某些进程长期占用CPU导致该进程无法获取到足够的CPU处理时间,而导致ANR重点关注下CPU的负载,各个进程总的CPU时间占用率,用户CPU时间占用率,核心态CPU时间占用率,以及iowait CPU时间占用率。
  2. 内存方面
    主要看当前应用native和dalvik层内存使用情况,结合系统给每个应用分配的最大内存来分析。

Android N 各种ANR的时间

Service Timeout

文件:ActiveServices.java
1
2
3
4
5
// 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; // 后台

broadcast Timeout

文件:ActivityManagerService.java
1
2
3
// 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; // 后台

InputDispatching Timeout

文件:ActivityManagerService.java
1
2
// How long we wait until we timeout on key dispatching.
static final int KEY_DISPATCHING_TIMEOUT = 5*1000;

ContentProvider Timeout

1
2
3
// How long we wait for an attached process to publish its content providers
// before we decide it must be hung.
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
这个时间的统计区间是在System_Server进程调用startProcessLocked之后会调用AMS.attachApplicationLocked,以这为起点,一直到provider进程installProvider以及publishContentProviders,调用到AMS.publishContentProviders为止。超过了这个时间就会系统就会杀掉Provider进程
其他文章
目录导航 置顶
  1. 1. 前言
  2. 2. ANR原因
  3. 3. ANR出现场景
  4. 4. ANR原因
  5. 5. 如何避免ANR
  6. 6. 分析ANR的重点
  7. 7. Android N 各种ANR的时间
请输入关键词进行搜索