天天看點

安卓卡頓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閃退,持久化當時資訊。

原理圖:

安卓卡頓ANR測試