一、 什麼是ANR
ANR,(Application Not Responding) 即應用程序無響應,在android應用中,當我們的UI線程被阻塞,就會彈出如下對話框,用戶可以選擇繼續等待或者關閉這個應用程序,這種現象我們稱之爲ANR.
二、 ANR的類型
ANR的類型大致分爲以下三種
1、主線程對輸入事件在5秒內沒有處理完畢 產生這種ANR的前提是要有輸入事件,如果用戶沒有觸發任何輸入事件,即便是主線程阻塞了,也不會產生ANR,因爲InputDispatcher沒有分發事件給應用程序,當然也不會檢測處理超時和報告ANR了。
2、主線程在執行BroadcastReceiver的onReceive函數時10秒內沒有執行完畢,後臺進程是60秒 這種情況的ANR系統不會顯示對話框提示,僅是輸出log而已。
3、主線程在執行Service的各個生命週期函數時20秒內沒有執行完畢,後臺進程爲200秒
同樣對這種情況的ANR系統也不會顯示對話框提示,僅是輸出log。
三種類型的ANR只有第一種會有彈框。
Type |
Method call |
Log sample |
time out |
Input dispatch |
onClick(),onTouch(),onKeydown(),onKeyup() |
Input dispatching timed out |
5 |
Broadcast |
onReceive() |
Timeout of broadcast |
FG: 10, BG 60 |
Service |
onBind(),onCreate(),onStartCommand(),onUnbind(),onDestroy() |
Timeout executing service |
FG: 20, BG 200 |
三、 ANR產生的原因
大致分爲兩類:
1.應用自身進程引起的問題,比如, 在oncreate ,onstart等生命週期中執行耗時操作,ui線程阻塞,掛起,死循環等
2,其他進程引起的,比如:io操作導致cpu使用過高,導致當前應用進程無法搶佔到cpu時間片
細分的話可以分爲以下一些情況:
- 耗時的網絡訪問
- 大量的數據讀寫
- 數據庫操作
- 硬件操作(比如camera)
- 調用thread的join()方法、sleep()方法、wait()方法或者等待線程鎖的時候
- service binder的數量達到上限
- system server中發生WatchDog ANR
- service忙導致超時無響應
- 其他線程持有鎖,導致主線程等待超時
- 其它線程終止或崩潰導致主線程一直等待...
四、如何避免ANR
- 耗時的工作()比如數據庫操作,I/O,網絡操作),採用單獨的工作線程處理
- 用Handler來處理UIthread和工作thread的交互
- 合理使用 Handler 來處理其他線程請求;
- 合理使用並遵循 Android 生命週期, 避免在 onCreate() and onResume() 做過多的事情;
- 使用一些架構形成規範來避免內存等問題,例如:MVP、RxJava;
- 經常使用工具來檢查內存問題,例如:MAT、TraceView、AS 自帶等工具;
- 避免加載大圖片引起內存不足導致 ANR;
- 避免內存泄露引起的 ANR。