1.什麼是ANR 在Android上,如果你的應用程式有一段時間響應不夠靈敏,系統會向用戶顯示一個對話框,這個對話框稱作應用程式無響應(ANR:Application Not Responding)對話框。用戶可以選擇讓程式繼續運行,但是,他們在使用你的應用程式時,並不希望每次都要處理這個對話框。因 ...
1.什麼是ANR
在Android上,如果你的應用程式有一段時間響應不夠靈敏,系統會向用戶顯示一個對話框,這個對話框稱作應用程式無響應(ANR:Application Not Responding)對話框。用戶可以選擇讓程式繼續運行,但是,他們在使用你的應用程式時,並不希望每次都要處理這個對話框。因此,在程式里對響應性能的設計很重要,這樣,系統不會顯示ANR給用戶。
2.ANR產生的原因
ANR產生的根本原因是APP阻塞了UI線程。在android系統中每個App只有一個UI線程,是在App創建時預設生成的,UI線程預設初始化了一個消息迴圈來處理UI消息,ANR往往就是處理UI消息超時了。那麼UI消息來源有哪些呢?主要有兩種來源:
2.1 來自於AMS的回調消息
在Android系統中,應用程式是有Android的四大組件組成,AMS負責對應用程式四大組件生命周期的管理,當AMS對應用程式組件的生命周期進行回調超過AMS定義的響應時間時,AMS就會報ANR。出現這種情況,一般是因為在這些組件的回調函數裡面進行了耗時操作(如網路操作、SD卡文件操作、資料庫操作、大量計算等),AMS對組件常見的回調函數及超時時間如下:
Activity: onCreate(), onResume(), onDestroy(), onKeyDown(), onClick()等,超時時間5s Application: onCreate(), onTerminate()等,超時時間5s Service: onCreate(), onStart(), onDestroy()等,超時時間20s BroadcastReceiver:onReceiver(),前臺APP廣播超時時間是10s,後臺App是60s
2.2 App自己的發出的消息
除了AMS對四大組件的回調消息運行在UI線程外,有些操作也是運行在UI線程的:
AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel()等,超時5s Mainthread handler: handleMessage(), post*(runnable r)等,超時5s
3.怎樣避免ANR
當我們知道ANR的產生原因之後,就可以較為輕鬆的避免ANR了。並且Android為我們提供了很多解決方法。主要歸為一下幾類。
1:UI線程儘量只做跟UI相關的工作,但一些複雜的UI操作,還是需要一些技巧來處理,不如你讓一個Button去setText一個10M的文本,UI肯定崩掉了,不過對於此類問題,分段載入貌似是最好的方法了。 2:讓耗時的工作(比如資料庫操作,I/O,連接網路或者別的有可能阻礙UI線程的操作)把它放入單獨的線程處理。 3:儘量用Handler來處理UIthread和別的thread之間的交互。
4.發佈的程式怎樣收集ANR異常
對於發佈的程式,ANR異常是很那捕獲不到的(我查找過很多資料,如果您有很好的捕獲辦法,歡迎再下方留言),所以我們需要採用其它的方法來分析ANR。app在產生ANR異常後,會將異常信息寫入"/data/anr/traces.txt"文件我們可以通過收集用戶的這個文件,就可以來獲取用戶產生ANR的地方了。
ANR的Log信息保存在:/data/anr/traces.txt,每一次新的ANR發生,會把之前的ANR信息覆蓋掉。
我在一個按鈕的onClick事件里寫瞭如下代碼
while(true){}
來故意產生一個ANR異常,然後打開/data/anr/traces.tx文件,主要有用的地方如下圖:
我們可以看到,在trace.txt文件里已經定位到異常產生的地方。所以,在用戶反饋界面,當我們發現戶反饋內容里是否出現了"無響應"等字眼的時候,就可以提示用戶是否上傳異常文件,來幫助我們改善產品之類的。當然,現在流氓猖狂,貌似做到這麼細緻產品的,為數不多了。
ANR屬於慢性崩潰,Android應用里的還存在著很多的強制崩潰,別如你執行了3/0了,空指針異常了等等,這些情況應用程式會直接崩掉,用戶體驗超級差
https://blog.csdn.net/itachi85/article/details/6918761