1潘拨、ANR是什么?
ANR英文全稱Application Not Responding办素,通俗來(lái)說(shuō)就是程序未響應(yīng)淘正!如果一個(gè)應(yīng)用無(wú)法響應(yīng)用戶的輸入,系統(tǒng)就會(huì)彈出一個(gè)ANR的對(duì)話框拓提,如下圖所示读恃,用戶可以自行選擇繼續(xù)等待還是停止當(dāng)前程序。
2、出現(xiàn)場(chǎng)景
1寺惫、主線程被IO操作阻塞疹吃,
2、主線程做耗時(shí)操作西雀,
3萨驶、主線程錯(cuò)誤的操作,如Thread.wait或者Thread.sleep等
Android系統(tǒng)出現(xiàn)下面兩種情況艇肴,就會(huì)彈出ANR對(duì)話框
1腔呜、應(yīng)用在5秒內(nèi)未響應(yīng)用戶輸入事件
2、BroadcastReceiver未在10秒內(nèi)完成相關(guān)處理
如何避免
耗時(shí)的操作全部交給子工作線程來(lái)處理再悼,UI線程只做ui方面的操作核畴。
1、使用AsyncTask處理耗時(shí)IO操作帮哈。
2膛檀、使用Thread或者HandlerThread時(shí)锰镀,調(diào)用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設(shè)置優(yōu)先級(jí)娘侍,否則仍然會(huì)降低程序響應(yīng),因?yàn)槟J(rèn)Thread的優(yōu)先級(jí)和主線程相同泳炉。
3憾筏、使用Handler處理工作線程結(jié)果,而不是使用Thread.wait()或者Thread.sleep()來(lái)阻塞主線程花鹅。
4氧腰、Activity的onCreate和onResume回調(diào)中盡量避免耗時(shí)的代碼
5、BroadcastReceiver中onReceive代碼也要盡量減少耗時(shí)刨肃,建議使用IntentService處理古拴。
如何定位
如果開(kāi)發(fā)機(jī)器上出現(xiàn)問(wèn)題,我們可以通過(guò)查看/data/anr/traces.txt即可真友,最新的ANR信息在最開(kāi)始部分黄痪。我們從stacktrace中即可找到出問(wèn)題的具體行數(shù)。本例中問(wèn)題出現(xiàn)在MainActivity.java 27行盔然,因?yàn)檫@里調(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過(guò)了60秒居然沒(méi)有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");
}
}
實(shí)際上已經(jīng)發(fā)生了ANR愈案,只是沒(méi)有進(jìn)行對(duì)話框彈出而已挺尾。這種ANR就是background ANR,即后臺(tái)程序的ANR站绪,我們可以通過(guò)過(guò)濾日志驗(yàn)證
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么遭铺?
當(dāng)然可以,在Android開(kāi)發(fā)者選項(xiàng)—>高級(jí)—>顯示所有”應(yīng)用程序無(wú)響應(yīng)“勾選即可對(duì)后臺(tái)ANR也進(jìn)行彈窗顯示,方便查看了解程序運(yùn)行情況魂挂。