Android中ANR的分析和解决( 七 )

BroadcastReceiver是Android的消息组件 , 用来组件之间、应用之间的消息传递 , 生命周期太短也不能开子线程处理耗时任务 , 耗时任务一般转交给IntentService或者JobIntentService去做 。
3、服务Service没有及时响应
Service是计算型组件 , 虽然在后台运行 , 但是本质上它也跑在主线程 , 如果你的服务要做任何CPU密集型(如MP3播放)或阻塞(如网络)操作 , 都要放在子线程中 , 否则耗时超过20s就会导致anr 。下面我在onStartCommand方法中休眠40秒 。
(1)模拟触发ANR:
Java@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {SystemClock.sleep(40000);//故意响应超时导致ANRreturn super.onStartCommand(intent, flags, startId);}(2)对应的Trace文件关键日志:
DALVIK THREADS (13)://虚拟机线程被阻塞"Signal Catcher" daemon prio=5 tid=3 Runnable| group="system" sCount=0 dsCount=0 flags=0 obj=0x13940108 self=0x7322e16400| sysTid=7658 nice=0 cgrp=default sched=0/0 handle=0x731c3304f0| state=R schedstat=( 5995782 10695989 10 ) utm=0 stm=0 core=3 HZ=100| stack=0x731c235000-0x731c237000 stackSize=1009KB| held mutexes= "mutator lock"(shared held)"main" prio=5 tid=1 Sleeping//主线程被阻塞| group="main" sCount=1 dsCount=0 flags=1 obj=0x73e64b08 self=0x7322e14c00| sysTid=7652 nice=-10 cgrp=default sched=0/0 handle=0x73a88cc548| state=S schedstat=( 595004855 101962599 596 ) utm=40 stm=18 core=2 HZ=100| stack=0x7fd05f2000-0x7fd05f4000 stackSize=8MB| held mutexes=at java.lang.Thread.sleep(Native method)- sleeping on <0x0e096f2a> (a java.lang.Object)at java.lang.Thread.sleep(Thread.java:373)- locked <0x0e096f2a> (a java.lang.Object)at java.lang.Thread.sleep(Thread.java:314)at android.os.SystemClock.sleep(SystemClock.java:127)//代码被阻塞的关键位置at com.example.anrtest.ANRService.onStartCommand(ANRService.java:17)//服务的onStartCommand方法at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3705)at android.app.ActivityThread.access$1600(ActivityThread.java:200)at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1688)at android.os.Handler.dispatchMessage(Handler.java:106)at android.os.Looper.loop(Looper.java:193)at android.app.ActivityThread.main(ActivityThread.java:6718)at java.lang.reflect.Method.invoke(Native method)at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)



推荐阅读