1.什么是ANR
在Android上浪读,如果你的應用程序有一段時間響應不夠靈敏筋栋,系統(tǒng)會向用戶顯示一個對話框胆建,這個對話框稱作應用程序無響應(ANR:Application Not Responding)對話框甥啄。用戶可以選擇讓程序繼續(xù)運行活尊,但是灰粮,他們在使用你的應用程序時仔涩,并不希望每次都要處理這個對話框。因此粘舟,在程序里對響應性能的設計很重要熔脂,這樣,系統(tǒng)不會顯示ANR給用戶柑肴。
2.ANR產(chǎn)生的原因
ANR產(chǎn)生的根本原因是APP阻塞了UI線程霞揉。在android系統(tǒng)中每個App只有一個UI線程,是在App創(chuàng)建時默認生成的晰骑,UI線程默認初始化了一個消息循環(huán)Looper來處理UI消息适秩,ANR往往就是處理UI消息超時了。那么UI消息來源有哪些呢些侍?主要有兩種來源:
? 2.1 來自于AMS的回調(diào)消息
? ? ? ? ?在Android系統(tǒng)中隶症,應用程序是有Android的四大組件組成,AMS負責對應用程序四大組件生? ? ?命? 周期的管理岗宣,當AMS對應用程序組件的生命周期進行回調(diào)超過AMS定義的響應時間時蚂会,AMS 就會報ANR。出現(xiàn)這種情況耗式,一般是因為在這些組件的回調(diào)函數(shù)里面進行了耗時操作(如網(wǎng)絡 操作胁住、SD卡文件操作、數(shù)據(jù)庫操作刊咳、大量計算等)彪见,AMS對組件常見的回調(diào)函數(shù)及超時時間
如下:
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自己的發(fā)出的消息
除了AMS對四大組件的回調(diào)消息運行在UI線程外酵镜,有些操作也是運行在UI線程的:
AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel()等,超時5sMainthreadhandler: handleMessage(), post*(runnable r)等柴钻,超時5s
3.怎樣避免ANR
當我們知道ANR的產(chǎn)生原因之后淮韭,就可以較為輕松的避免ANR了。并且Android為我們提供了很多解決方法贴届。主要歸為一下幾類靠粪。
1:UI線程盡量只做跟UI相關(guān)的工作蜡吧,但一些復雜的UI操作,還是需要一些技巧來處理占键,不如你讓一個Button去setText一個10M的文本昔善,UI肯定崩掉了,不過對于此類問題捞慌,分段加載貌似是最好的方法了耀鸦。
2:讓耗時的工作(比如數(shù)據(jù)庫操作,I/O啸澡,連接網(wǎng)絡或者別的有可能阻礙UI線程的操作)把它放入單獨的線程處理袖订。
3:盡量用Handler來處理UIthread和別的thread之間的交互。
4.發(fā)布的程序怎樣收集ANR異常
? 對于發(fā)布的程序嗅虏,ANR異常是很那捕獲不到的(我查找過很多資料洛姑,如果您有很好的捕獲辦法,歡迎再下方留言)皮服,所以我們需要采用其它的方法來分析ANR楞艾。app在產(chǎn)生ANR異常后,會將異常信息寫入"/data/anr/traces.txt"文件我們可以通過收集用戶的這個文件龄广,就可以來獲取用戶產(chǎn)生ANR的地方了硫眯。
我在一個按鈕的onClick事件里寫了如下代碼
while(true){}
來故意產(chǎn)生一個ANR異常,然后打開/data/anr/traces.tx文件择同,主要有用的地方如下圖:
我們可以看到两入,在trace.txt文件里已經(jīng)定位到異常產(chǎn)生的地方。所以敲才,在用戶反饋界面裹纳,當我們發(fā)現(xiàn)戶反饋內(nèi)容里是否出現(xiàn)了"無響應"等字眼的時候,就可以提示用戶是否上傳異常文件紧武,來幫助我們改善產(chǎn)品之類的剃氧。當然,現(xiàn)在流氓猖狂阻星,貌似做到這么細致產(chǎn)品的朋鞍,為數(shù)不多了。
ANR屬于慢性崩潰妥箕,Android應用里的還存在著很多的強制崩潰滥酥,別如你執(zhí)行了3/0了,空指針異常了等等矾踱,這些情況應用程序會直接崩掉,用戶體驗超級差疏哗。