ANR学习笔记

Posted by CoderBao Blog on March 26, 2016

ANR

Android系统为了防止某些应用会在一段时间内反应迟钝,因而弹出的ANR对话框。

ANR触发条件

  • 5秒内未响应input event,包括key和touch两种事件
  • 10秒内未执行完的BroadcastReceiver
  • 20秒内未执行完的Service,注意:Service也是执行在主线程中。

需要注意ANR的场景

IO,网络,数据库,复杂计算(如bitmap压缩等)

避免ANR的方法:在UI线程外的worker thread做耗时操作。

改善响应速度的方法

  • ProgressBar
  • worker thread中计算
  • 如果是应用启动耗时长,展示splash screen或尽快渲染出main view,同时显示进度
  • 使用SystraceTraceview等发现性能瓶颈

推荐阅读shelves源码,学习如何在配置改变时保存任务,在Activity销毁时取消任务。

ANR原理

InputManager.cpp负责管理InputReader.cpp(从底层读取输入事件)和InputDispatcher.cpp(分发key/touch输入事件,两者判断ANR的条件有差异)的生死,如果InputDispatcher.cpp在分发时出现上一个事件还没做完/没有窗口拿到焦点等问题,就会调用InputDispatcher::onANRLocked()–>InputDispatcher::doNotifyANRLockedInterruptible()–>com_android_server_input_InputManagerService.cpp中的NativeInputManager::notifyANR()–>本地方法调用java方法,InputManagerService.notifyANR() –>InputMonitor.notifyANR()–>通知WMS和AMS,AMS显示ANR对话框。

ANR分析和解决

可以看这篇Android ANR 如何分析和解决里分析的场景。应该从以下几点着手:

  • CPU
    • CPU接近100%,说明是CPU负荷太重
    • CPU占用不高,说明是主线程阻塞了
  • IOwait
    • 高,说明主线程有IO操作
  • traces.txt 位于/data/anr/目录下,获取方式:

      chmod 777 /data/anr
    
      rm /data/anr/traces.txt
    	
      ps
    	
      kill -3 PID
    	
      adb pull data/anr/traces.txt ./mytraces.txt 
    

参考文献:

ANR官方文档

ANR触发原理(what triggers ANR?)

ANR源码流程

最佳实践–性能