給你一個Demo 看看這時你要怎麼快速定位ANR?

yilian發表於2019-11-14

前言?

我們程式設計師去面試的時候,做題必不可少。今天,就來給大家講解一下來自阿里巴巴的提問:給你一個Demo,你如何快速定位ANR

一、前期基礎知識儲備

1.ANR錯誤定義:在Android上,如果你的應用程式有一段時間響應不夠靈敏,系統會向使用者顯示一個對話方塊,這個對話方塊稱作“應用程式無響應”(ANR:Application Not Responding)對話方塊。使用者可以選擇“等待”而讓程式繼續執行,也可以選擇“強制關閉”。因此,在程式裡對響應效能的設計很重要,這樣,系統不會顯示ANR給使用者。

預設情況下,在Android中Activity的最長執行時間是5秒(主要型別),BroadcastReceiver的最長執行時間的則是10秒,ServiceTimeout的最長執行時間是20秒(少數型別)。超出就會提示應用程式無響應(ANR錯誤)。

image
image

2.ANR錯誤出現原因:只有當應用程式的UI執行緒響應超時才會引起ANR 超時產生的原因包括:①當前事件沒有機會處理,例如UI執行緒正在響應另外的事件,當前事件被某個事件給阻塞掉了;②當前事件正在處理 但是由於耗時太長沒有能及時的完成。其他原因:③在BroadcastReceiver裡做耗時的操作或計算;④CPU使用過高;⑤發生了死鎖;⑥耗時操作的動畫需要大量的計算工作,可能導致CPU負載過重。

二、ANR定位方式及最佳化

1.ANR錯誤定位——如果開發機器上出現ANR問題時,系統會生成一個traces.txt的檔案放在/data/anr下,最新的ANR資訊在最開始部分。透過adb命令將其匯出到本地,輸入以下字元:

$adb pull data/anr/traces.txt .

2.供選的最佳化ANR問題的方式:

1)為了執行一個長時間的耗時操作而建立一個工作執行緒最方便高效的方式是使用AsyncTask,只需要繼承AsyncTask並實現doInBackground()方法來執行任務即可。為了把任務執行的進度呈現給使用者,你可以執行publishProgress()方法,這個方法會觸發onProgressUpdate()的回撥方法。在onProgressUpdate()的回撥方法中(它執行在UI執行緒),你可以執行通知使用者進度的操作,例如:

2)如果你實現了Thread或者HandlerThread,請確保你的UI執行緒不會因為等待工作執行緒的某個任務而去執行Thread.wait()或者Thread.sleep()。UI執行緒不應該去等待工作執行緒完成某個任務,你的UI執行緒應該提供一個Handler給其他工作執行緒,這樣工作執行緒能夠透過這個Handler在任務結束的時候通知UI執行緒。例如:
繼承Thread類

實現Runnable介面

使用HandlerThread

3)開發在日常的開發過程中使用Thread或者HandlerThread,可以嘗試呼叫Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設定較低的優先順序,否則仍然會降低程式響應,因為預設Thread的優先順序和主執行緒相同。

4)Activity的onCreate和onResume回撥中儘量避免耗時的程式碼,應該儘可能的做比較少的事情,其實,任何執行在UI執行緒中的方法都應該儘可能簡短快速。類似網路或者DB操作等可能長時間執行的操作,或者是類似調整bitmap大小等需要長時間計算的操作,都應該執行在工作執行緒中。

5)BroadcastReceiver中onReceive程式碼也要儘量減少耗時。如果必須在onReceive方法中執行耗時操作,建議使用IntentService進行處理,IntentService集開啟執行緒和自動關閉服務兩種功能於一身,本身非常靈活。

6)增加介面響應性(互動層面),這是一個成熟應用必備的標誌—通常來說,100ms - 200ms是使用者能夠察覺到卡頓的上限。如果你的程式在啟動階段有一個耗時的初始化操作,可以考慮顯示一個閃屏,要麼儘快的顯示主介面,然後馬上顯示一個載入的對話方塊,非同步載入資料。無論哪種情況,你都應該顯示一個進度資訊,以免使用者感覺程式有卡頓的情況。

三、輔助處理ANR問題的工具

1.Traceview - 系統效能分析工具,用於定位應用程式碼中的耗時操作

image
image

①選好應用的程式,執行一段應用操作,從圖中的上半部分,可以看到各個執行緒的各個方法的執行時間;

②從圖中的下半部分,可以該段操作中具體呼叫的方法和每個方法的執行時間、執行次數。佔CPU的百分比;

image
image

該圖是具體的方法執行時間分佈圖,我們重點關注其中的“Incl Real Time”這一時間指標,其為方法的實際呼叫時間,單位毫秒,檢視時點選Incl Real Time進行排列,方法會根據時間長短進行排列,其中超過500ms的方法我們都該重點關注。

2.Systrace - Android4.1新增的應用效能資料取樣和分析工具(與google引擎聯合開發 使用時藉助chorme瀏覽器)

image
image

連線手機,進行一段操作,系統會生成一份Html檔案,在谷歌瀏覽器中開啟,如圖:

①Sytrace會顯示在這段操作期間所有的程式資訊,在其中找到自己的程式,可以看到在測試程式中,我們定位UI Thread,可以看到裡面的系統方法,這是UI渲染時的呼叫方法,上面有一個個的圈,綠色圈代表幀渲染時間是16.6ms(Android系統渲染UI介面時間為1秒60幀,每幀即16.6ms),超過該值的幀用紅色圈標註;

②點選紅色圈的標註幀,可以看到Sytrace給出的Alert,具體檢視可發現,給出了該幀具體的渲染時間為36.71ms,超過16.6ms,UI渲染時會發生掉幀的情況,即卡頓,再往下看,可以看到系統給出的建議和超時的主要方法。拿到這個方法再結合Traceview工具,進行具體分析,找到自己的程式碼,進行最佳化,減少耗時。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69952849/viewspace-2664094/,如需轉載,請註明出處,否則將追究法律責任。

相關文章