Android ANR 詳解


ANR簡介

  • ANR,是“Application Not Responding”的縮寫,即“應用程序無響應”。在Android中,ActivityManagerService(簡稱AMS)和WindowManagerService(簡稱WMS)會監測應用程序的響應時間,如果應用程序主線程(即UI線程)在超時時間內對輸入事件沒有處理完畢,或者對特定操作沒有執行完畢,就會出現ANR。對於輸入事件沒有處理完畢產生的ANR,Android會顯示一個對話框,提示用戶當前應用程序沒有響應,用戶可以選擇繼續等待或者關閉這個應用程序(也就是殺掉這個應用程序的進程)。

為什么會有ANR

ANR的產生需要同時滿足三個條件:
  • 主線程:只有應用程序進程的主線程響應超時才會產生ANR;
  • 超時時間:產生ANR的上下文不同,超時時間也會不同,但只要在這個時間上限內沒有響應就會ANR
  • 輸入事件/特定操作:輸入事件是指按鍵、觸屏等設備輸入事件,特定操作是指BroadcastReceiver和Service的生命周期中的各個函數,產生ANR的上下文不同,導致ANR的原因也會不同;

針對這三個條件,有以下三種情況會觸發ANR,詳細說明如下。

  • 1、主線程對輸入事件在5秒內沒有處理完畢
Android的事件系統從2.3開始做了完全不同的實現,原先2.2中是在Java層實現的,但在2.3中整體轉移到了C++層,本書基於2.3以后的版本進行說明。我們先簡單了解一下產生這種ANR的整個流程。

當應用程序的Window處於Active狀態並且能夠接收輸入事件(例如按鍵事件、觸摸事件等)時,系統底層上報的事件就會被InputDispatcher分發給這個應用程序,應用程序的主線程通過InputChannel讀取輸入事件並交給界面視圖處理,界面視圖是一個樹狀結構,DecorView是視圖樹的根,事件從樹根開始一層一層向端點(例如一個Button)傳遞。我們通常會注冊一個監聽器來接收並處理事件,或者創建自定義的視圖控件來處理事件。

InputDispatcher運行在系統進程(進程名為system_server)的一個單獨的線程中,應用程序的主線程在處理事件的過程中,InputDispatcher會不斷的檢測處理過程是否超時,一旦超時,會通過一系列的回調通知WMS的notifyANR函數,最終會調用到AMS中mHandler對象里的SHOW_NOT_RESPONDING_MSG這個case,此時界面上就顯示系統提示對話框了,同時使用logcat命令查看log(日志信息)也可以看到關於ANR的信息。一下子出現了好幾個重要的名詞,要深入了解這種情況的ANR,需要熟悉Android的事件機制,本次不做解析,這里只需要記住他們的功能:
  • Window:具體指的是PhoneWindow對象,表示一個能夠顯示的窗口,它能夠接收系統分發的各種輸入事件;
  • InputDispatcher:將系統上報的輸入事件分發給當前活動的窗口;
  • InputChannel:InputDispatcher和應用程序分別運行在兩個不同的進程中,InputDispatcher就是通過InputChannel將事件對象傳遞給應用進程的。
    注意:產生這種ANR的前提是要有輸入事件,如果用戶沒有觸發任何輸入事件,即便是主線程阻塞了,也不會產生ANR,因為InputDispatcher沒有分發事件給應用程序,當然也不會檢測處理超時和報告ANR了。
  • 2、主線程在執行BroadcastReceiver的onReceive函數時10秒內沒有執行完畢

    BroadcastReceiver(簡稱BR)的onReceive函數運行在主線程中,當這個函數超過10秒鍾沒有返回就會觸發ANR。不過對這種情況的ANR系統不會顯示對話框提示,僅是輸出log而已。

     

  • 3、主線程在執行Service的各個生命周期函數時20秒內沒有執行完畢

    Service的各個生命周期函數也運行在主線程中,當這些函數超過20秒鍾沒有返回就會觸發ANR。同樣對這種情況的ANR系統也不會顯示對話框提示,僅是輸出log。

三種ANR中只有第1種會顯示系統提示對話框,因為用戶正在做界面交互操作,如果長時間沒有任何響應,會讓用戶懷疑設備死機了,大多數人此時會開始亂按,甚至拔出電池重啟,給用戶的體驗肯定是非常糟糕的。

三種ANR發生時都會在log中輸出錯誤信息,你會發現各個應用進程和系統進程的函數堆棧信息都輸出到了一個/data/anr/traces.txt的文件中,這個文件是分析ANR原因的關鍵文件,同時在日志中還會看到當時的CPU使用率,這也是重要信息,可以利用它們分析ANR問題。

這三種ANR不是孤立的,有可能會相互影響。例如一個應用程序進程中同時有一個正在顯示的Activity和一個正在處理消息的BroadcastReceiver,它們都運行在這個進程的主線程中。如果BR的onReceive函數沒有返回,此時用戶點擊屏幕,而onReceive超過5秒仍然沒有返回,主線程無法處理用戶輸入事件,就會引起第1種ANR。如果繼續超過10秒沒有返回,又會引起第2種ANR


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM