What is ANR?
ANR 即 Application Not Responding,程序無響應異常。在 Android 系統中,當一個應用程序長時間沒有響應用戶操作的時候,就會彈出一個 ANR 異常提示框,提供用戶退出當前應用的選擇。彈出 ANR 提示框的應用程序的用戶體驗是相當差的,所以我們在寫 Android 應用程序時,應該盡可能避免應用程序出現 ANR 異常。
什么時候會出現 ANR ?
在 Android 中,程序的響應性是由 Activity Manager 與 Window Manager 這兩個系統服務來負責監控的。當系統監測到下面的條件之一時會顯示 ANR 對話框:
- 對輸入事件(例如硬件點擊或者屏幕觸摸事件),5秒內都無響應;
- BroadReceiver 不能夠在 10 秒內結束接收到任務;
如何避免 ANR 異常?
- 針對第一類 ANR 異常:Android 系統中的所有操作默認都是在應用程序的主線程,即 UI 線程中排隊執行的,那么當遇到一個相對比較耗時的操作,如網絡請求、DB 操作、Bitmap 計算等,線程就會因為等待這些操作完成而無法響應用戶事件,在等待時間超過 5 秒時,就會彈出 ANR 提示框。因此,針對這類 ANR 異常,通常的解決措施就是開啟一個工作線程來執行耗時操作,等到操作完成時,再采用線程間通信方式將結果提交給 UI 線程加以顯示。
- 針對第二類 ANR 異常:BroadcastReceiver 有特定執行時間的限制說明了 BroadcastReceiver 應該用于執行一些簡短快速地任務,而不能用于執行耗時較長的任務。當需要執行耗時任務時,不同于第一類 ANR
異常,此時不是采用通過工作線程來執行復雜任務的方式,而應該發送一個 Intent 給 Service,由 Service 來執行該耗時任務。因為 BroadcastReceiver 的生命周期很短(在 onReceive() 執行后,BroadcastReceiver 的實例就會被銷毀),而此時執行耗時操作的子線程很有可能還沒有結束,若該子線程所在的宿主進程中還有其他組件正在運行的話,那么還好,若沒有的話,那么該進程就屬于一個空進程,其優先級很低,在系統內存較低的情況下,會最先被系統殺死。所以為了確保耗時任務能夠順利執行,應該使用 Service 來執行該耗時任務。
Tip: 可以使用 StrictMode 來幫助尋找因為不小心加入到 UI 線程的潛在的長時間執行的操作,例如網絡或者 DB 相關的任務。