ANR 在 Android開發中并不陌生,遇到 ANR 有時讓我們很苦惱,自己平時也遇到過這樣的問題,今天來聊聊 Android 中 ANR 那點事并記錄在此,以防下次遇到我們就知道該如何分析了。
ANR定義
簡單說下官方解釋,ANR,Application Not Responding,即應用程式沒有響應,Android 系統會向使用者顯示一個程式無響應對話框,使用者可以選擇等待或者強制關閉。
出現場景
- 按鍵或觸摸事件 5s 内無響應;
- BroadcastReceiver 10s 内無法處理完成;
- Service 在 20s 時間内無法處理完成;
發生 ANR 基本上都會出現無法響應對話框,除了一些背景程式的 ANR,造成 ANR 的原因很多,比如:
- UI 主線程被其他操作阻塞;
- 主線程存在耗時操作(本地 IO操作、網絡通路、循環等);
如何分析
關于發生 ANR 截取的 log 和 trace 這裡就不多說了
1、CPU 問題
- 在 Monkeylog.log 檔案中定位到 “anr in” 位置,檢視 cpu usage ,total 占用,如發現接近100%,暫時判斷為 cpu 問題。
-
然後在 logcat.log 檔案中定位到 “not responding” 發生時間,并截取
cpuinfo.log 中時間點前後 5s 的 log,然後計算 CPU 占中,看哪個程序用的多,在酌情分析子產品的 CPU 占中。
2、GC 問題
- 定位到 logcat.log 檔案中 “not responding” 發生時間點;
- 去檢視發生 ANR 時間點對應的 trace 檔案,定位到應用報名,若Dalvik Thread主線程顯示“SUSPENDED”,則為記憶體問題;
- 截取 ANR 發生時間點前 5s 的 log,分析 “dalvikvm” 列印的 Paused GC 耗時,如果過多則定位為 GC 問題,需要檢視這 5s 件發生了哪些耗時的操作。
注意:發生 GC 的程序 id 需要和目前發生 ANR 的線程 id 的要一緻
如何避免
- 合理使用 UI 主線程,耗時操作放入其他線程工作;
- 合理使用 Handler 來處理其他線程請求;
- 合理使用并遵循 Android 生命周期, 避免在 onCreate() and onResume() 做過多的事情;
- 使用一些架構形成規範來避免記憶體等問題,例如:MVP、RxJava;
- 經常使用工具來檢查記憶體問題,例如:MAT、TraceView、AS 自帶等工具;
- 避免加載大圖檔引起記憶體不足導緻 ANR;
- 避免記憶體洩露引起的 ANR。
比如官方例子中:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
// Do the long-running work in here
// 耗時操作放這裡
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
// This is called each time you call publishProgress()
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
// This is called when doInBackground() is finished
// 耗時操作完成後 Post 到 UI 主線程
protected void onPostExecute(Long result) {
showNotification("Downloaded " + result + " bytes");
}
}
友好處理
一般情況下, 超過100至200毫秒使用者會感覺程式有些緩慢。是以,可以做一些比較友好的 UI 提示頁面,比如:ProgressBar,來表明目前正在處理,使得使用者不會去一直點選頁面,減少輸入即可能減少 ANR 出現幾率,因為按鍵5s不響應是會出現 ANR 的。
可以使用性能工具來優化我們的 App,如 Systrace 和 Traceview 。
關于記憶體洩露分析可以檢視之前總結的 Android 記憶體洩漏工具使用分析
如果有錯,歡迎大家指正!
參考
官方文檔
Android 記憶體洩漏工具使用分析
Keeping Your App Responsive