ANR是因为负责更新UI的应用程序主线程无法处理用户输入事件或绘制
埋炸弹—拆炸弹—Boom很形象
实验环境:
Android Studio3.2
gradle:3.2.0
jdk1.8
实体机红米Note4X
ANR主要发生条件
- Service Timeout:比如前台服务在20s内未执行完成;
- 对于前台服务,则超时为SERVICE_TIMEOUT = 20s;(ActivityService里的数值变量为SERVICE_TIMEOUT)
- 对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT = 200s (数值变量为SERVICE_BACKGROUND_TIMEOUT)
- BroadcastQueue Timeout:比如前台广播在10s内未执行完成
- ContentProvider Timeout:内容提供者,在publish过超时10s;
- InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。
注意事项
- 主线程正在进行长时间的计算,代码运行过慢,时间超过5秒
- 正在执行涉及主线程上I / O的慢速操作。(网络和文件存读操作)
- 当前进程主线程同步等待跨进程结果返回时间过长
- 互斥锁争用造成线程排队阻塞
- 死锁
当线程进入等待状态时会发生死锁,因为另一个线程拥有所需的资源,而另一个线程也在等待第一个线程拥有的资源。如果应用程序的主线程处于这种情况下,则可能会发生ANR。
死锁是计算机科学中经过充分研究的现象,并且可以使用死锁预防算法来避免死锁。
线程死锁举例:
A是主线程持有猪肉,需要茄子;B线程持有茄子,需要牛肉;C线程持有牛肉需要猪肉;A在等B释放资源拿到茄子,B在等C释放资源拿到牛肉,C在等A资源释放资源拿到猪肉,那么大家都在等另一个先进行操作,但是谁都没动手,就造成线程死锁。 - 广播接收器处理过于慢,即onReceiver()里处理时间过长,此时用IntentService处理更佳,因为其内部提供有辅助线程
ANR诊断手段
- 启用后台ANR对话框
仅当在设备的“ 开发人员”选项中启用了“ 显示所有ANR”时,Android才会为需要花费太长时间才能处理广播消息的应用程序显示ANR对话框。因此,并非总是向用户显示后台ANR对话框,但是该应用仍可能遇到性能问题。 - 可以使用Traceview之类的工具来查看,若使用Android Studio 3.2或更高版本,则应改用 CPU Profiler来检查
.trace
通过对应用日志进行检测而 捕获的文件Debug
,记录新的方法跟踪信息,保存.trace
文件并检查应用进程的实时CPU使用率。TraceView:
- shell命令查看ANR崩溃日志进行相关分析
当遇到ANR时,Android会存储跟踪信息。在较旧的OS版本/data/anr/traces.txt
上,设备上只有一个文件。在较新的OS版本中,存在多个/data/anr/anr_*
文件。您可以通过使用adb作为root用户从设备或仿真器访问ANR跟踪 ,此处实验真机并未root:
1.adb shell
先进入adb shell 命令模式,之后可以免除每次输入命令都要加adb关键字.
2.ls /data/anr
通过此命令查看系统是否存储有anr日志文件traces.txt,如果该目录下什么都没有,那系统没有生成 anr 日志,无需进行日志分析。
注:此处ls 是LS的小写
3.cat /data/anr/traces.txt >/mnt/sdcard/<filename>.txt
将日志导出至手机本地存储,从文件管理器进入本地存储获取查看
网友评论