Android--ANR分析

1、ANR是什么?
ANR英文全稱Application Not Responding,通俗來說就是程序未響應!如果一個應用無法響應用戶的輸入,系統(tǒng)就會彈出一個ANR的對話框,如下圖所示,用戶可以自行選擇繼續(xù)等待還是停止當前程序。

2、出現(xiàn)場景
1、主線程被IO操作阻塞,
2、主線程做耗時操作,
3、主線程錯誤的操作,如Thread.wait或者Thread.sleep等

Android系統(tǒng)出現(xiàn)下面兩種情況,就會彈出ANR對話框
1、應用在5秒內(nèi)未響應用戶輸入事件
2、BroadcastReceiver未在10秒內(nèi)完成相關處理

如何避免
耗時的操作全部交給子工作線程來處理,UI線程只做ui方面的操作。
1、使用AsyncTask處理耗時IO操作。
2、使用Thread或者HandlerThread時,調(diào)用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置優(yōu)先級,否則仍然會降低程序響應,因為默認Thread的優(yōu)先級和主線程相同。
3、使用Handler處理工作線程結果,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程。
4、Activity的onCreate和onResume回調(diào)中盡量避免耗時的代碼
5、BroadcastReceiver中onReceive代碼也要盡量減少耗時,建議使用IntentService處理。

如何定位
如果開發(fā)機器上出現(xiàn)問題,我們可以通過查看/data/anr/traces.txt即可,最新的ANR信息在最開始部分。我們從stacktrace中即可找到出問題的具體行數(shù)。本例中問題出現(xiàn)在MainActivity.java 27行,因為這里調(diào)用了Thread.sleep方法。

root@htc_m8tl:/ # cat /data/anr/traces.txt | more


----- pid 30307 at 2015-05-30 14:51:14 -----
Cmd line: com.example.androidyue.bitmapdemo

JNI: CheckJNI is off; workarounds are off; pins=0; globals=272

DALVIK THREADS:
(mutexes: tll=0 tsl=0 tscl=0 ghl=0)

"main" prio=5 tid=1 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 obj=0x416eaf18 self=0x416d8650
  | sysTid=30307 nice=0 sched=0/0 cgrp=apps handle=1074565528
  | state=S schedstat=( 0 0 0 ) utm=5 stm=4 core=3
  at java.lang.VMThread.sleep(Native Method)
  at java.lang.Thread.sleep(Thread.java:1044)
  at java.lang.Thread.sleep(Thread.java:1026)
  at com.example.androidyue.bitmapdemo.MainActivity$1.run(MainActivity.java:27)
  at android.app.Activity.runOnUiThread(Activity.java:4794)
  at com.example.androidyue.bitmapdemo.MainActivity.onResume(MainActivity.java:33)
  at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1282)
  at android.app.Activity.performResume(Activity.java:5405)

** BroadcastReceiver過了60秒居然沒有ANR?**

public class NetworkReceiver extends BroadcastReceiver{
    private static final String LOGTAG = "NetworkReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(LOGTAG, "onReceive intent=" + intent);
        try {
            Thread.sleep(60000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.i(LOGTAG, "onReceive end");
    }
}

實際上已經(jīng)發(fā)生了ANR,只是沒有進行對話框彈出而已。這種ANR就是background ANR,即后臺程序的ANR,我們可以通過過濾日志驗證

adb logcat | grep "NetworkReceiver|ActivityManager|WindowManager"
I/NetworkReceiver( 4109): onReceive intent=Intent { act=android.net.conn.CONNECTIVITY_CHANGE flg=0x8000010 cmp=com.example.androidyue.bitmapdemo/.NetworkReceiver (has extras) }
I/ActivityManager(  462): No longer want com.android.exchange (pid 1054): empty #17
I/NetworkReceiver( 4109): onReceive end
W/BroadcastQueue(  462): Receiver during timeout: ResolveInfo{5342dde4 com.example.androidyue.bitmapdemo.NetworkReceiver p=0 o=0 m=0x108000}
E/ActivityManager(  462): ANR in com.example.androidyue.bitmapdemo
E/ActivityManager(  462): Reason: Broadcast of Intent { act=android.net.conn.CONNECTIVITY_CHANGE flg=0x8000010 cmp=com.example.androidyue.bitmapdemo/.NetworkReceiver (has extras) }
E/ActivityManager(  462): Load: 0.37 / 0.2 / 0.14
E/ActivityManager(  462): CPU usage from 26047ms to 0ms ago:
E/ActivityManager(  462):   0.4% 58/adbd: 0% user + 0.4% kernel / faults: 1501 minor
E/ActivityManager(  462):   0.3% 462/system_server: 0.1% user + 0.1% kernel
E/ActivityManager(  462):   0% 4109/com.example.androidyue.bitmapdemo: 0% user + 0% kernel / faults: 6 minor
E/ActivityManager(  462): 1.5% TOTAL: 0.5% user + 0.9% kernel + 0% softirq
E/ActivityManager(  462): CPU usage from 87ms to 589ms later:
E/ActivityManager(  462):   1.8% 58/adbd: 0% user + 1.8% kernel / faults: 30 minor
E/ActivityManager(  462):     1.8% 58/adbd: 0% user + 1.8% kernel
E/ActivityManager(  462): 4% TOTAL: 0% user + 4% kernel
W/ActivityManager(  462): Killing ProcessRecord{5326d418 4109:com.example.androidyue.bitmapdemo/u0a10063}: background ANR
I/ActivityManager(  462): Process com.example.androidyue.bitmapdemo (pid 4109) has died.

可以更容易了解background ANR么?
當然可以,在Android開發(fā)者選項—>高級—>顯示所有”應用程序無響應“勾選即可對后臺ANR也進行彈窗顯示,方便查看了解程序運行情況。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容