ANR:Application Not Responding,即應用程序無響應。數據庫
在Android中,ActivityManagerService(簡稱AMS)和WindowManagerService(簡稱WMS)會監測應用程序的響應時間,若是應用程序主線程(即UI線程)在超時時間內對輸入事件沒有處理完畢,或者對特定操做沒有執行完畢,就會出現ANR。json
對於輸入事件沒有處理完畢產生的ANR,Android會顯示一個對話框,提示用戶當前應用程序沒有響應,用戶能夠選擇繼續等待或者關閉這個應用程序(也就是殺掉這個應用程序的進程)。網絡
ANR通常有三種類型:app
ANR產生的常見緣由:異步
能夠從log中搜索「ANR in」或「am_anr」,會找到ANR發生的log,該行會包含了ANR的時間、進程、是何種ANR等信息。ide
ANR產生時,系統會生成一個traces.txt的文件放在/data/anr/下。 能夠經過adb命令將其導出到本地:
adb pull data/anr/traces.txt函數
trace文件記錄了發生ANR先後該進程的各個線程的stack。oop
1.合理使用UI主線程,耗時操做放入其餘線程工做。post
1.1 UI線程儘可能只作跟UI相關的工做。spa
1.2 耗時的工做(好比數據庫操做,I/O,鏈接網絡或者別的有可能阻礙UI線程的操做)把它放入單獨的線程處理。
2.儘可能用Handler來處理UI thread和別的thread之間的交互。
3.合理使用並遵循Android生命週期,避免在onCreate()和onResume()作過多的事情。
4.sharedPreference的使用:
4.1 sharedPreference的commit()方法是同步的,apply()方法通常是異步執行的。在主線程不要用其commit(),用apply()替換。
4.2 sharedPreference的寫是全量寫而非增量寫,因此儘可能都修改完同一apply,避免改一點apply一次(apply()方法在Activity stop的時候主線程會等待寫入完成,提交屢次就很容易卡)。而且存儲文本也不宜過大,這樣會很慢。另外,若是寫入的是json或者xml,因爲須要加和刪轉義符號,速度會比較慢。
5.若是主線程阻塞,開闢單獨的子線程來處理耗時阻塞事務。
6.若是I/O阻塞,通常來講就是文件讀寫或數據庫操做執行在主線程了,能夠經過開闢子線程的方式異步執行。
7.若是內存不夠用,增大VM內存,使用largeHeap屬性,排查內存泄露。
各個組件的生命週期函數都不該該有太耗時的操做。
Activity的全部生命週期回調、Service的onCreate()、BroadcastReceiver的onReceive(開個IntentService去執行相應操做)、
ContentProvider的onCreate()是執行在主線程的。
沒有使用子線程的looper的Handler的handleMessage,
post(Runnable)是執行在主線程的。
AsyncTask的回調中除了doInBackground,其餘都是執行在主線程的。
View的post(Runnable)是執行在主線程的。
一些同步的操做主線程有可能被鎖,須要等待其餘線程釋放相應鎖才能繼續執行,這樣會有必定的ANR風險。對於這種狀況有時也能夠用異步線程來執行相應的邏輯。另外, 咱們要避免死鎖的發生(主線程被死鎖基本就等於要發生ANR了)。