安卓卡頓ANR測試

卡頓ANR與Android就是天生的朋友,從Android第一天誕生直到現在的8核CPU,Android還是未能擺脫頁面不流暢,卡,死機的詬病,所以個人認爲卡頓ANR測試是性能測試最主要的一塊。

卡頓簡單的來說,就是手機沒有及時響應、頁面延遲,出現丟幀的現象,或者點擊無響應。絕大多數的卡頓,稍等片刻系統就會恢復正常,但假如超過5S,就可能會引發手機ANR,造成更高級別的警告。如圖所示:

1.什麼會引發ANR?

在Android裏,應用程序的響應性是由Activity Manager和WindowManager系統服務監視的 。當它監測到以下情況中的一個時,Android就會針對特定的應用程序顯示ANR:

ANR一般有三種類型:

1)KeyDispatchTimeout(5 seconds) --主要類型按鍵或觸摸事件在特定時間內無響應

2)BroadcastTimeout(10 seconds) --BroadcastReceiver在特定時間內無法處理完成

3)ServiceTimeout(20 seconds) --小概率類型 Service在特定的時間內無法處理完成

這三種原因都會造成ANR,但是第一種情況基本上佔了所有ANR的百分之九十以上,第三種的情況微乎其微。這三種ANR不是孤立的,有可能會相互影響。例如一個應用程序進程中同時有一個正在顯示的Activity和一個正在處理消息的BroadcastReceiver,它們都運行在這個進程的主線程中。如果BR的onReceive函數沒有返回,此時用戶點擊屏幕,而onReceive超過5秒仍然沒有返回,主線程無法處理用戶輸入事件,就會引起第1種ANR。如果繼續超過10秒沒有返回,又會引起第2種ANR。發生ANR的主要原因是潛在的耗時操作,例如網絡或數據庫操作,或者高耗時的計算如改變位圖尺寸,應該在子線程裏(或者以數據庫操作爲例,通過異步請求的方式)來完成。然而,不是說你的主線程阻塞在那裏等待子線程的完成——也不是調用 Thread.wait()或是Thread.sleep()。替代的方法是,主線程應該爲子線程提供一個Handler,以便完成時能夠提交給主線程。以這種方式設計你的應用程序,將能保證你的主線程保持對輸入的響應性並能避免由於5秒輸入事件的超時引發的ANR對話框。

三種ANR發生時都會在log中輸出錯誤信息,你會發現各個應用進程和系統進程的函數堆棧信息都輸出到了一個/data/anr/traces.txt的文件中,ROOT手機導出該文件後,分析此日誌可以得出一些結論,但traces文件信息比較抽象,難理解。總的來說,日誌難收集,結果難分析。

2.如何避免ANR?

1) 運行在主線程裏的任何方法都儘可能少做事情。特別是,Activity應該在它的關鍵生命週期方法(如onCreate()和onResume())裏儘可能少的去做創建操作。(可以採用重新開啓子線程的方式,然後使用Handler+Message的方式做一些操作,比如更新主線程中的ui等)

2) 應用程序應該避免在BroadcastReceiver裏做耗時的操作或計算。但不再是在子線程裏做這些任務(因爲 BroadcastReceiver的生命週期短),替代的是,如果響應Intent廣播需要執行一個耗時的動作的話,應用程序應該啓動一個 Service。(此處需要注意的是可以在廣播接受者中啓動Service,但是卻不可以在Service中啓動broadcasereciver,關於原因後續會有介紹,此處不是本文重點)

3)避免在Intent Receiver裏啓動一個Activity,因爲它會創建一個新的畫面,並從當前用戶正在運行的程序上搶奪焦點。如果你的應用程序在響應Intent廣 播時需要向用戶展示什麼,你應該使用Notification Manager來實現。

TraceView是android SDK中自帶的一個性能測試工具,可以在Tools目錄下找到。TraceView能很精確的查看到每一個類,每一個類方法的執行時間。APP卡頓我們只需要保留當時的traceview文件,通過查看該文件,就可以定位絕大部分問題。

通過Debug.startMethodTracing(String FileName)和Debug.stopMethodTracing()來記錄一段時間內方法執行情況。

在主線程中不停的插入一個輕量級別的操作,如果該變量在指定的時間內,沒有改變,則說明此刻APP卡頓。卡把ANR這種警告變成錯誤讓APP閃退,持久化當時信息。

原理圖:




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