ANR (Application Not Responding) 是 Android 中一个独有的概念。当你在操作 App 时候感觉界面卡顿,卡顿超过一定时间就会出现ARN 对话框。出现 ANR 主要是因为我们在主线程中做了太多耗时操作。这时你可以选择"等待"按钮,等待应用程序结束主线程的耗时操作,或者选择"确定"按钮,结束这个应用程序。
ANR 产生的原因
只有应用程序的 UI 线程响应超时才会引起 ANR,超时产生原因一般有两种。
- 当前的事件没有机会得到处理,例如 UI 线程正在响应另外一个事件,当前事件由于某种原因被阻塞了。
- 当前事件正在处理,但是由于耗时太长没能及时完成。
根据 ANR 产生的原因不同,超时时间也不尽相同,从本质上讲,产生 ANR 的原因有三种,大致可以对应到 Android 中的四大组件的三个(Activity/View,BroadcastReceived 和 Service)。
- KeyDispatchTimeout,原因是 View 的按钮事件或者触摸事件在特定的事件(5秒)内无法得到响应。
- BroadcastTimeout,原因是 BroadcastReceived 的 onReceived 函数运行在主线程中,在特定的事件(10秒)内无法完成处理。
- ServiceTimeout,原因是 Service 的各个生命周期函数在特定事件(20秒)内无法完成处理。
典型的 ANR 问题场景
- 应用程序 UI 线程存在耗时操作,例如在 UI 线程中进行网络请求,数据库操作或者文件操作,可能导致 UI 线程无法及时处理用户输入等。在 Android 之后,如果在 UI 线程中进行网络操作,将会抛出 NetworkOnMainThreadException 异常。
- 应用程序的 UI 线程等待子线程释放某个锁,从而无法处理用户的输入。
- 耗时的动画需要大量的计算工作,可能导致 CPU 负载过重。
降低ANR出现的频率
降低 ANR 出现的频率,尊重一个原则:
不要在主线程做繁重的任务。
- 避免在主线程读取数据。Andrioid 禁止在主线程从网络读数据,但是没有禁止从本地数据库或者其他地方获取数据,这种操作 ANR 风险很大,也会造成丢帧。
- sharePreference 是全量更新而不是增量更新,所以尽量统一 apply,并且存储的文件不宜过大,过大的文件可以考虑写入到文件或者本地的数据库中。
- 不要在 BroadcastReceived 的 onRecieve 中干活,可以选择开个 IntentService 去执行响应操作。
- 各个组件的生命周期不应该有太过耗时的操作。
- 尽量避免主线程的被锁的情况,在一些同步操作中可能出现主线程被锁的情况,这样会有一定的 ANR 风险。
- 避免一次性价值大量的大图高清图。
网友评论