極力推薦文章:歡迎收藏
Android 干貨分享
閱讀五分鍾,每日十點,和您一起終身學習,這里是程序員Android
ANR(Application Not Responding )
應用無響應的簡稱,是為了在 APP
卡死時,用戶 可以強制退出APP
的選擇,從而避免卡機無響應問題,這是Android
系統的一種自我保護機制。
通過本篇閱讀,您將學習到以下內容
- 什么是ANR
- ANR的類型
- ANR 產生的原因
- 如何分析解決 ANR問題
- ANR 問題分析解決建議
- MTK 平台 ANR問題分析
1. 什么是ANR
在Android
中,應用程序響應由Activity Manager
和Window Manager
系統服務進行監視。ANR(Application Not Responding )
,則是Android
的一種自我保護措施,當主線程出現卡頓時候,Android
系統會給用戶一個彈出提示,讓用戶手動選擇繼續等待還是強制關閉此APP
。
當Android檢測到以下情況之一時,Android
將顯示特定應用程序的ANR
對話框,比如以下三種情況下ANR
將經常發生:
UI Thread
超過5 s
沒有響應Broadcast
廣播超過10 s
沒響應Service
服務超過20s
沒響應
因此,為避免ANR
發生,請不要在主線程中進行耗時操作,耗時操作請盡量在子線程中運行。- 發生
ANR
截圖 如下:
2. ANR的類型
ANR
在 Android
手機中很常見,按其相應類型可以分為以下 常見 三種類型。
ANR類型:
- 按鍵響應分發超時(Key Dispatch Timeout)
默認5 s
,超過則會出現ANR。- 廣播超時(Broadcast Timeout)
默認10 s
,超過則會出現ANR。- 服務超時(Service Timeout)
默認20 s
,超過則會出現ANR。
3. ANR 產生的原因
在Android
系統中,APP
通常運行在一個UI Thread
或者叫MainThread
里。並且Android
中只有一個MainThread
和Main Message Queue
。MainThread
主要用於UI
的繪制、事件響應,監聽與接收事件處理等功能。Main Message Queue
主要存放用戶要處理消息的隊列,主線程MainThread
從消息隊列Main Message Queue
中取消息Message
后,盡快分發下去,一旦某條消息分發超時,則ANR
可能發生。
因此,當ANR
發生時,我們要分析ANR
產生的原因,也就是查找消息處理不及時的原因。例如可以從以下幾個疑問點進行分析:
-
- 為什么
APP
不能獲取CPU
時間片?
- 為什么
-
APP
是否是等待一些沒能及時處理的事件完成?
- 3 . 消息處理流程是不是太復雜?
4. 如何分析解決 ANR問題
在分析ANR
時有一些常見的模式可供選擇:
APP
正在主線程上進行緩慢的I/O
操作。APP
正在主線程中進行很復雜的計算操作- 主線程正在對另一個進程執行同步
Binder
程序調用,但另一個進程需要很長時間才能返回結果。 - 主線程在等待另一個正在長時間執行塊操作的子線程時被阻塞。
- 主線程因為另一個線程死鎖,無論是
Bind
調用還是主線程調用,都不能讓主線程等待很久,更不能在主線程中進行復雜的計算。
知道產生ANR的原因,那么如何避免ANR 問題呢?
a.Strict mode
使用StrictMode
可以幫助您在開發應用程序時在主線程上發現意外的I / O
操作。 您可以在application
或activity
使用StrictMode
。
b.關閉 ANR Dialog 提示
查看方法ANR控制的方法:
設置---- 開發者選項---顯示所有ANR
注意 :
如沒有開發者選項,請進入設置---關於手機--- 多次連擊 版本號 即可打開隱藏的開發者選項的item
c.Traceview
Traceview獲取正在運行的應用程序的跟蹤信息,分析此traces.txt
文件 可以推測出主線程在忙於某些事情。
traces
文件通常保存在/data/anr/traces.txt
下,你可以直接用adb cat
查看,或者 adb pull
出來都可以。
- 直接查看trace 信息
個人不太建議
adb root
adb shell
cat /data/anr/traces.txt
- pull trace 文件到桌面
建議使用此方法
adb root
adb remount
adb pull /data/anr/traces.txt C:\Users\Administrator\Desktop\新建文件夾
5. ANR 問題分析解決建議
分析查看ANR
原因,接着解決ANR
問題。
-
耗時操作
請放在工作現場中進行,可以使用Handler、AsyncTask
等。 -
IO 操作
(比如:網絡操作、存儲操作等)也是引起ANR的常見因素。強烈建議在工作線程中進行。 -
程序鎖競爭
某些情況,ANR
產生的原因不是直接因為在主線程中產生的。 比如: 工作線程對某個資源
等上鎖,恰好此時,主線程需要此資源
,如等待超時,則此時ANR可能發生。
- 死鎖
當主線程因為請求一個其他線程正在持有的資源而進入等待狀態時,ANR
可能會發生。
- 廣播接收慢
應用程序可以通過廣播接收器響應廣播消息,例如啟用或禁用飛行模式或更改連接狀態。 當應用程序花費太長時間來處理廣播消息時,理論上超過10s 未處理完成,ANR
可能會發生。
廣播 ANR發生在下列情況下:
onReceive()
方法長時間未執行完畢。
盡量避免在onReceive()
中進行耗時操作。
- 廣播接收者調用
goAsync()
方法並且未能在PendingResult
對象上調用finish()
。
如要處理的廣播內容較多,請使用IntentService
進行處理。
比如下面例子:
- 不建議在onReceive 方法中進行耗時操作,超過10s 未處理,會引起ANR
- 建議使用
IntentService
,避免ANR發生
您的廣播接收機可以使用goAsync()
來通知系統需要更多的時間來處理消息。 但是,您應該在PendingResult
對象上調用finish()
。 以下示例顯示如何調用finish()以讓系統回收廣播接收器並避免ANR:
6. MTK 平台 ANR問題分析
前提,抓取一份ANR
的 MTK log
。
1.event_log
中 搜索關鍵字 am_anr
或者anr
,分析並查看ANR
原因
2. main_log
中 搜索關鍵字Application Not Responding
或者anr
,分析並查看ANR
原因。
3. MTK ANR 策略建議
常見ANR 舉例分析如下:
至此,本篇已結束,如有不對的地方,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!