(自己翻譯的,轉載請註明,謝謝。缺圖、排版問題以及無效連結,我會慢慢修正,之前請和AndroidSDK文檔對照來看)
就算你寫的代碼能夠通過世界上所有的效能測試,你的應用仍然有可能使使用者陷入狂暴狀態。缺乏響應性 — 反應慢、某些情況會卡、處理輸入的時間非常長 — 的應用就能做到這一點。
在Android中,系統通過彈出一個“應用無響應(ANR)”對話方塊給使用者,來對抗一段時間沒有相應的應用。使用者可以在這個對話方塊中,選擇繼續你的應用,但是使用者不會喜歡在用你的應用的時候總是看到這個對話方塊。所以,在你的應用中設計響應性是很重要的,系統就不會彈出ANR給使用者。
一般來說,當應用對使用者輸入沒有相應的時候,系統彈出ANR。例如,如果一個應用阻塞在某些輸入輸出操作(例如頻繁地網路請求),應用的主線程就不會繼續響應使用者的輸入事件。過了一段時間後,系統會認為這個應用已經廢了,於是就彈出一個ANR來讓使用者選擇是否強制關閉應用。
同樣地,如果你的應用花了太多的時間在構建精巧的資料結構或者計算遊戲的下一步上面,系統就會以為你的應用廢了。利用下面要說的技術使你的計算更高效是非常重要的,但是就算是最高效的代碼,仍然會消耗時間。
在這兩種情況下,建立一個子線程來完成工作是常用的修複手段。這樣,主線程(響應UI事件的迴圈)就會一直運行,系統就不會認為你的代碼死了。一般來說,線程是屬於類層級,所以,你可以認為響應性是一個類層級的問題。(跟基本行為比較,基本行為,如下描述,是方法層級的內容。)
An ANR dialog displayed to the user.
本文檔討論了Android系統是如何判斷一個應用是否無響應,以及提供保證代碼響應性的指導。
本文檔包含了一下內容:
- ANR是什麼觸發的?
- 如何避免ANR?
- 增強響應性。
ANR是什麼觸發的?
在Android中,應用的響應性是被ActivityManager和WindowManager兩個系統服務監視的。對於一個應用,在以下兩種情況,Android會彈出ANR:
- 輸入事件(按鍵、點擊螢幕之類)之後5秒沒有相應。
- 一個
BroadcastReceiver
執行超過了10秒。
如何避免ANR
通過上面給出的ANR的定義,讓我們看看為什麼Android應用會無響應,以及如何使你的應用避免這個。
一般來說,Android應用會整個運行在一個線程(主線程)裡。這意味著,在主線程,任何需要很長時間完成的動作,由於導致了你的應用沒機會處理輸入事件或者廣播的Intent,都會觸發ANR對話方塊。
因此,任何在主線程工作的方法,都應該只做最少的事情。 Activity的關鍵生命週期方法,例如onCreate()
和onResume()
裡,更要做儘可能少的事。潛在的耗時運算,例如網路或資料庫操作,或者進行類似縮放位元影像這樣的大量的數學運算,都應該在子線程做。(對於資料庫操作,可以通過一個非同步方法呼叫,而不必放進另一個線程)。這並不意味著你的主線程應該阻塞住等著子線程,無論是通過Thread.wait()
還是Thread.sleep()
。你的主線程應該提供一個Handler
來給子線程結束後返回結果。如此設計你的應用,可以讓你的主線程對輸入保持小於5秒的響應速度,從而避免ANR對話方塊。如果其它的線程涉及展示UI,應該遵循同樣的實踐。
對IntentReceiver的執行時間顯示,暗示了它應該做的事情,是後台小規模的工作,類似儲存設定或者註冊Notification一類。所以,跟在主線程的方法一樣,應用應該避免在BroadcastReceiver中進行潛在的耗時操作或運算。除了在子線程中處理大量密集任務(因為BroadcastReceiver生命週期是很短的)。當一個潛在的耗時操作需要返回一個廣播Intent時,你的應用應該啟動一個 Service
。額外提醒,你應該避免從一個IntentReceiver裡啟動Activity,這將會跳出一個新的介面,並把使用者正在做的工作打斷。如果你的應用收到廣播Intent之後需要展示給使用者什麼的話,它應該使用 Notification Manager
。
增強響應性
一般來說,100到200毫秒是使用者感到“卡”的門檻。下面是避免ANR以及加快你的應用響應額外的建議。
- 如果你的應用需要等著後台工作的結果,展示出它的進度。 (可以使用
ProgressBar
或ProgressDialog
)
- 對於遊戲,大量的計算應該放到子線程。
- 如果你的應用初始化耗時很長,考慮使用一個SplashScreen或者儘快進入主介面然後再非同步地慢慢填充。 在這兩種情況,你應該提供給使用者一個進度條之類的東西,表明你的應用還沒死。
轉至http://blog.csdn.net/sirdonker/article/details/5647805