轉(zhuǎn)自:
http://rayleeya.iteye.com/blog/1955652
ANR的全稱是application not responding掠哥,意思就是程序未響應(yīng)。
默認(rèn)情況下腮介,在android中Activity的最長執(zhí)行時(shí)間是5秒,BroadcastReceiver的最長執(zhí)行時(shí)間則是10秒端衰。
在Android里叠洗,應(yīng)用程序的響應(yīng)性是由Activity Manager和WindowManager系統(tǒng)服務(wù)監(jiān)視的。當(dāng)它監(jiān)測(cè)到以下情況中的一個(gè)時(shí)旅东,Android就會(huì)針對(duì)特定的應(yīng)用程序顯示ANR:
- dispatchTimeout 輸入事件分發(fā)超時(shí)灭抑,一般是由于主線程(即UI線程)在5秒之內(nèi)沒有響應(yīng)輸入事件。(例如抵代,按鍵按下腾节,屏幕觸摸)
- BroadcastReceiver沒有在系統(tǒng)設(shè)定的時(shí)間內(nèi)(默認(rèn)10秒)完成并返回。
為什么會(huì)有ANR
ANR的產(chǎn)生需要同時(shí)滿足三個(gè)條件:
主線程:只有應(yīng)用程序進(jìn)程的主線程響應(yīng)超時(shí)才會(huì)產(chǎn)生ANR荤牍;
超時(shí)時(shí)間:產(chǎn)生ANR的上下文不同禀倔,超時(shí)時(shí)間也會(huì)不同,但只要在這個(gè)時(shí)間上限內(nèi)沒有響應(yīng)就會(huì)ANR参淫;
輸入事件/特定操作:輸入事件是指按鍵、觸屏等設(shè)備輸入事件愧杯,特定操作是指BroadcastReceiver和Service的生命周期中的各個(gè)函數(shù)涎才,產(chǎn)生ANR的上下文不同,導(dǎo)致ANR的原因也會(huì)不同力九。
針對(duì)這三個(gè)條件耍铜,有以下三種情況會(huì)觸發(fā)ANR,詳細(xì)說明如下跌前。
- 主線程對(duì)輸入事件在5秒內(nèi)沒有處理完畢
當(dāng)應(yīng)用程序的Window
處于 Active 狀態(tài)并且能夠接收輸入事件(例如按鍵事件棕兼、觸摸事件等)時(shí),系統(tǒng)底層上報(bào)的事件就會(huì)被InputDispatcher分發(fā)給這個(gè)應(yīng)用程序抵乓,應(yīng)用程序的主線程通過InputChannel讀取輸入事件并交給界面視圖處理伴挚,界面視圖是一個(gè)樹狀結(jié)構(gòu),DecorView是視圖樹的根灾炭,事件從樹根開始一層一層向端點(diǎn)(例如一個(gè)Button)傳遞茎芋。我們通常會(huì)注冊(cè)一個(gè)監(jiān)聽器來接收并處理事件,或者創(chuàng)建自定義的視圖控件來處理事件蜈出。
InputDispatcher運(yùn)行在系統(tǒng)進(jìn)程(進(jìn)程名為system_server)的一個(gè)單獨(dú)的線程中田弥,應(yīng)用程序的主線程在處理事件的過程中,InputDispatcher會(huì)不斷的檢測(cè)處理過程是否超時(shí)铡原,一旦超時(shí)偷厦,會(huì)通過一系列的回調(diào)通知WMS的notifyANR函數(shù)商叹,最終會(huì)調(diào)用到AMS中mHandler對(duì)象里的SHOW_NOT_RESPONDING_MSG這個(gè)case,此時(shí)界面上就顯示系統(tǒng)提示對(duì)話框了只泼,同時(shí)使用logcat命令查看log(日志信息)也可以看到關(guān)于ANR的信息剖笙。InputDispatcher就是那個(gè)愛打“小報(bào)告”的家伙。
Window:具體指的是PhoneWindow對(duì)象辜妓,表示一個(gè)能夠顯示的窗口枯途,它能夠接收系統(tǒng)分發(fā)的各種輸入事件;
InputDispatcher:將系統(tǒng)上報(bào)的輸入事件分發(fā)給當(dāng)前活動(dòng)的窗口籍滴;
InputChannel:InputDispatcher和應(yīng)用程序分別運(yùn)行在兩個(gè)不同的進(jìn)程中酪夷,InputDispatcher就是通過InputChannel將事件對(duì)象傳遞給應(yīng)用進(jìn)程的。
注意:產(chǎn)生這種ANR的前提是要有輸入事件孽惰,如果用戶沒有觸發(fā)任何輸入事件晚岭,即便是主線程阻塞了,也不會(huì)產(chǎn)生ANR勋功,因?yàn)镮nputDispatcher沒有分發(fā)事件給應(yīng)用程序坦报,當(dāng)然也不會(huì)檢測(cè)處理超時(shí)和報(bào)告ANR了。
- 主線程在執(zhí)行BroadcastReceiver的onReceive函數(shù)時(shí)10秒內(nèi)沒有執(zhí)行完畢
BroadcastReceiver(簡(jiǎn)稱BR)的onReceive函數(shù)運(yùn)行在主線程中狂鞋,當(dāng)這個(gè)函數(shù)超過10秒鐘沒有返回就會(huì)觸發(fā)ANR片择。不過對(duì)這種情況的ANR系統(tǒng)不會(huì)顯示對(duì)話框提示,僅是輸出log而已骚揍。
- 主線程在執(zhí)行Service的各個(gè)生命周期函數(shù)時(shí)20秒內(nèi)沒有執(zhí)行完畢
Service的各個(gè)生命周期函數(shù)也運(yùn)行在主線程中字管,當(dāng)這些函數(shù)超過20秒鐘沒有返回就會(huì)觸發(fā)ANR。同樣對(duì)這種情況的ANR系統(tǒng)也不會(huì)顯示對(duì)話框提示信不,僅是輸出log嘲叔。
三種ANR中只有第1種會(huì)顯示系統(tǒng)提示對(duì)話框,因?yàn)橛脩粽谧鼋缑娼换ゲ僮鞒榛睿绻L時(shí)間沒有任何響應(yīng)硫戈,會(huì)讓用戶懷疑設(shè)備死機(jī)了,大多數(shù)人此時(shí)會(huì)開始亂按下硕,甚至拔出電池重啟丁逝,給用戶的體驗(yàn)肯定是非常糟糕的。
三種ANR發(fā)生時(shí)都會(huì)在log中輸出錯(cuò)誤信息梭姓,你會(huì)發(fā)現(xiàn)各個(gè)應(yīng)用進(jìn)程和系統(tǒng)進(jìn)程的函數(shù)堆棧信息都輸出到了一個(gè)/data/anr/traces.txt的文件中果港,這個(gè)文件是分析ANR原因的關(guān)鍵文件,同時(shí)在日志中還會(huì)看到當(dāng)時(shí)的CPU使用率糊昙,這也是重要信息辛掠,在后面的章節(jié)會(huì)詳細(xì)介紹如何利用它們分析ANR問題。
這三種ANR不是孤立的,有可能會(huì)相互影響萝衩。例如一個(gè)應(yīng)用程序進(jìn)程中同時(shí)有一個(gè)正在顯示的Activity和一個(gè)正在處理消息的BroadcastReceiver回挽,它們都運(yùn)行在這個(gè)進(jìn)程的主線程中。如果BR的onReceive函數(shù)沒有返回猩谊,此時(shí)用戶點(diǎn)擊屏幕千劈,而onReceive超過5秒仍然沒有返回,主線程無法處理用戶輸入事件牌捷,就會(huì)引起第1種ANR墙牌。如果繼續(xù)超過10秒沒有返回,又會(huì)引起第2種ANR暗甥。