Android 性能优化之 ANR 优化
- ANR 是 Application Not Responding 的缩写,即应用程序无响应,当 Android 应用的 UI 主线程无法响应用户操作超过一定的时间(处于阻塞状态的时间过长,可能进行耗时的网络请求、文件读写或复杂计算等),如果此时应用位于前台,系统会弹出"应用程序无响应"对话框,用于提示用户,允许用户选择"等待"或"强制关闭",相当于当系统检测到应用应用的 UI 主线程在一定时间内无法及时响应处理用户输入事件或绘制操作,就会触发 ANR
会触发 ANR 的场景
- Activity:在 5 秒内未完成 onResume 或者在 5 秒内未响应输入事件(如按键或屏幕触摸)
- BroadcastReceiver: 前台广播的 onReceive 方法耗时超过大概 10 秒,后台广播超过大概 60 秒
- Service:前台服务的 onCreate、onStartCommand、onBind 等方法 20 秒内没有执行完成,后台服务则在 200 秒内
- ContentProvider:query、insert、publish 等方法在 10 秒内没有执行完成
- JobScheduler 超时:JobService 未在指定时间内(几秒内)完成操作(比如未调用 JobService#setNotification)
- 主线程处理耗时操作(比如文件 IO 操作或数据库操作等)
- 布局过于复杂(嵌套层级深、过度绘制)、频繁执行重绘刷新
- 主线程与子线程发生死锁,或长时间等待同步锁(未正确使用同步机制)
- 系统内存不足(内存泄漏等导致)、CPU 负载过高导致系统服务响应延迟、频繁 GC 导致主线程被抢占
BROADCAST_TIMEOUT_MSG 广播超时
- 发送广播时根据广播发送中的 intent 是否带有 FLAG_RECEIVER_FOREGROUND 标记可以分为前台广播和后台广播
java
前台广播超时时间
- Android 13 及以下版本 10 秒
- Android 14 及以上版本,10-20 秒,具体取决于进程是否已耗尽 CPU
后台广播超时时间
- Android 13 及以下版本 60 秒
- Android 14 及以上版本,60-120 秒,具体取决于进程是否已耗尽 CPU
优化策略
- 主线程只做轻量级的操作,使用子线程处理耗时任务
- 减少布局复杂度,避免复杂的 UI 渲染,减少 UI 刷新频率
- 使用异步机制或优化同步逻辑,避免死锁和等待同步锁(尝试尽量减少在主线程和子线程之间发生的锁竞争)
- 根据设备性能加载不同资源(区分设备性能,动态调整资源加载策略),及时避免内存泄漏(包括及时释放大内存对象),通过线程避免频繁创建和销毁线程
排查检测
- Google Play 收集到的用户感知 ANR 率
- 当 ANR 发生时,系统会在 Logcat 中生成日志,包含关键信息(如阻塞的线程、调用栈),搜索关键字来定位 ANR 问题
- 导出 /data/anr/traces.txt(低版本)排查或使用 adb bugreport 获取 bug 报告(内部包含 ANR 日志),通过分析主线程堆栈来定位原因
- 在开发阶段启用 StrictMode 严格模式,检测主线程中的违规操作(比如磁盘操作或网络访问),以触发警告
- 通过启用后台 ANR 对话框,在设备的开发者选项中启用了显示所有 ANR 时,比如针对长时间处理广播消息也会显示 ANR 对话框
- 实现 ANR-WatchDog 检测 ANR,通过自定义线程周期性检查主线程状态(利用子线程轮询主线程消息队列),若长时间未响应则触发日志记录
- 通过腾讯 Matrix 集成 ANR 监控模块,支持后台 ANR 捕获
- 利用 Systrace 系统跟踪工具监控系统性能,识别主线程阻塞的原因
- 利用 Android Studio Profiler 分析应用性能,排查问题原因