ANR異常

1)什麼引發了ANR?
       在Android裏,應用程序的響應性是由Activity Manager和Window Manager系統服務監視的。當它監測到以下情況中的一個時,Android就會針對特定的應用程序顯示ANR:
       · 在5秒內沒有響應輸入的事件(例如,按鍵按下,屏幕觸摸)
       · BroadcastReceiver在10秒內沒有執行完畢
       通常情況下,下面這些做法會導致ANR
              1、在主線程內進行網絡操作
              2、在主線程內進行一些緩慢的磁盤操作(例如執行沒有優化過的SQL查詢)
       應用應該在5秒或者10秒內響應,否則用戶會覺得“這個應用很垃圾”“爛”“慢”…等等
2)如何避免ANR?
       Android應用程序通常是運行在一個單獨的線程(例如,main)裏。這意味着你的應用程序所做的事情如果在主線程裏佔用了太長的時間的話,就會引發ANR對話框,因爲你的應用程序並沒有給自己機會來處理輸入事件或者Intent廣播。
       因此,運行在主線程裏的任何方法都儘可能少做事情。特別是,Activity應該在它的關鍵生命週期方法(如onCreate()和onResume())裏儘可能少的去做創建操作。潛在的耗時操作,例如網絡或數據庫操作,或者高耗時的計算如改變位圖尺寸,應該在子線程裏(或者以數據庫操作爲例,通過異步請求的方式)來完成。然而,不是說你的主線程阻塞在那裏等待子線程的完成——也不是調用Thread.wait()或是Thread.sleep()。替代的方法是,主線程應該爲子線程提供一個Handler,以便完成時能夠提交給主線程。以這種方式設計你的應用程序,將能保證你的主線程保持對輸入的響應性並能避免由於5秒輸入事件的超時引發的ANR對話框。這種做法應該在其它顯示UI的線程裏效仿,因爲它們都受相同的超時影響。
       IntentReceiver執行時間的特殊限制意味着它應該做:在後臺裏做小的、瑣碎的工作如保存設定或者註冊一個Notification。和在主線程裏調用的其它方法一樣,應用程序應該避免在BroadcastReceiver裏做耗時的操作或計算。但不再是在子線程裏做這些任務(因爲BroadcastReceiver的生命週期短),替代的是,如果響應Intent廣播需要執行一個耗時的動作的話,應用程序應該啓動一個Service。順便提及一句,你也應該避免在Intent Receiver裏啓動一個Activity,因爲它會創建一個新的畫面,並從當前用戶正在運行的程序上搶奪焦點。如果你的應用程序在響應Intent廣播時需要向用戶展示什麼,你應該使用Notification Manager來實現。
3)增強響應靈敏性
       一般來說,在應用程序裏,100到200ms是用戶能感知阻滯的時間閾值。因此,這裏有一些額外的技巧來避免ANR,並有助於讓你的應用程序看起來有響應性。
       · 如果你的應用程序爲響應用戶輸入正在後臺工作的話,可以顯示工作的進度(ProgressBar和ProgressDialog對這種情況來說很有用)。
       · 特別是遊戲,在子線程裏做移動的計算。
       · 如果你的應用程序有一個耗時的初始化過程的話,考慮可以顯示一個Splash Screen或者快速顯示主畫面並異步來填充這些信息。在這兩種情況下,你都應該顯示正在進行的進度,以免用戶認爲應用程序被凍結了。

       補充:在面網易的Android工程師時問到了Service的ANR異常。首先Service是不可以處理耗時操作的,因爲Service也是生存在主線程的,處理耗時的操作只能放在新的線程裏面。如果Service處理超時操作,會出現ANR異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章