如何解决Android的ANR问题?

首先我们要理解关于Android的ANR的一些理论知识:

1.什么是Android的ANR?

    ANR顾名思义就是Application Not Response,即应用无响应。

2.ANR分为三类:

   KeyDispatchTimeOut(5 秒)

   BroadcastTimeOut(10 秒)

   ServiceTimeOut(20 秒)

3.三类ANR分别发生的原因:

    KeyDispatchTimeOut:

    按键或触摸事件在5秒内无法完成,即从按键分发给app开始计时,如果此事件在5秒内无法完成就会报出此类ANR提示。

    此时超时的原因一般有两种:1.当前的事件没有来得及处理,(UI线程正在处理前一个事件,没有及时完成或者looper因为某些原因被阻塞了);2.当前的事件正在处理,但没有及时完成。

   BroadcastTimeOut:

   BroadcastReceiver在10秒内无法处理完成相关逻辑

   ServiceTimeOut:

    这种是小概率事件,Service在20秒内没有执行完成相关逻辑

4.如何避免ANR的发生呢?

    这里以KeyDispatchTimeOut为例:

     (1)UI线程尽量做UI相关的操作。

     (2)耗时的操作(比如数据库、IO流操作、连接网络或者别的有可能阻碍UI线程的操作)放入单独的线程进行处理。

     (3)尽量用Handler来处理UI线程与别的线程之间的通信。

5.补充说明下什么是UI线程:

   UI线程主要包括以下:

      (1)Activity的生命周期的方法、onKeyDown()、onClick()。

      (2)AsyncTask:onPreExecute()、onProgressUpdate()、onPostExecute()、onCancel()等等

     (3)Mainthead Handler: handleMessage()、    post(Runnable)   等等

     (4)其他的

了解了相关ANR的理论,现在就要具体实践了。

1.如何分析ANR?

    首先我们看log:

04-01 13:12:11.572 I/InputDispatcher( 220): Application is not responding:Window{2b263310com.android.email/com.android.email.activity.SplitScreenActivitypaused=false}.  5009.8ms since event, 5009.5ms since waitstarted
04-01 13:12:11.572 I/WindowManager( 220): Input event dispatching timedout sending tocom.android.email/com.android.email.activity.SplitScreenActivity
04-01 13:12:14.123 I/Process(  220): Sending signal. PID: 21404 SIG: 3---发生ANR的时间和生成trace.txt的时间
04-01 13:12:14.123 I/dalvikvm(21404):threadid=4: reacting to signal 3 
04-01 13:12:15.872 E/ActivityManager(  220): ANR in com.android.email(com.android.email/.activity.SplitScreenActivity)
04-01 13:12:15.872 E/ActivityManager(  220): Reason:keyDispatchingTimedOut
04-01 13:12:15.872 E/ActivityManager(  220): Load: 8.68 / 8.37 / 8.53
04-01 13:12:15.872 E/ActivityManager(  220): CPUusage from 4361ms to 699ms ago ----CPU在ANR发生前的使用情况
04-01 13:12:15.872 E/ActivityManager(  220):   5.5%21404/com.android.email: 1.3% user + 4.1% kernel / faults: 10 minor
04-01 13:12:15.872 E/ActivityManager(  220):   4.3%220/system_server: 2.7% user + 1.5% kernel / faults: 11 minor 2 major
04-01 13:12:15.872 E/ActivityManager(  220):   0.9%52/spi_qsd.0: 0% user + 0.9% kernel
04-01 13:12:15.872 E/ActivityManager(  220):   0.5%65/irq/170-cyttsp-: 0% user + 0.5% kernel
04-01 13:12:15.872 E/ActivityManager(  220):   0.5%296/com.android.systemui: 0.5% user + 0% kernel
04-01 13:12:15.872 E/ActivityManager(  220): 100%TOTAL: 4.8% user + 7.6% kernel + 87% iowait
04-01 13:12:15.872 E/ActivityManager(  220): CPUusage from 3697ms to 4223ms later:-- ANR后CPU的使用量
04-01 13:12:15.872 E/ActivityManager(  220):   25%21404/com.android.email: 25% user + 0% kernel / faults: 191 minor
04-01 13:12:15.872 E/ActivityManager(  220):    16% 21603/__eas(par.hakan: 16% user + 0% kernel
04-01 13:12:15.872 E/ActivityManager(  220):    7.2% 21406/GC: 7.2% user + 0% kernel
04-01 13:12:15.872 E/ActivityManager(  220):    1.8% 21409/Compiler: 1.8% user + 0% kernel
04-01 13:12:15.872 E/ActivityManager(  220):   5.5%220/system_server: 0% user + 5.5% kernel / faults: 1 minor
04-01 13:12:15.872 E/ActivityManager(  220):    5.5% 263/InputDispatcher: 0% user + 5.5% kernel
04-01 13:12:15.872 E/ActivityManager(  220): 32%TOTAL: 28% user + 3.7% kernel

从LOG可以看出ANR的类型,CPU的使用情况,如果CPU使用量接近100%,说明当前设备很忙,有可能是CPU饥饿导致了ANR
如果CPU使用量很少,说明主线程被BLOCK了
如果IOwait很高,说明ANR有可能是主线程在进行I/O操作造成的
除了看LOG,解决ANR还得需要trace.txt文件,
如何获取呢?可以用如下命令获取
$chmod 777 /data/anr
$rm /data/anr/traces.txt
$ps
$kill -3 PID
adbpull data/anr/traces.txt ./mytraces.txt
从trace.txt文件,看到最多的是如下的信息:
-----pid 21404 at 2011-04-01 13:12:14 -----  
Cmdline: com.android.email

DALVIK THREADS:
(mutexes: tll=0tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
"main" prio=5 tid=1NATIVE
  | group="main" sCount=1 dsCount=0obj=0x2aad2248 self=0xcf70
  | sysTid=21404 nice=0 sched=0/0cgrp=[fopen-error:2] handle=1876218976
  atandroid.os.MessageQueue.nativePollOnce(Native Method)
  atandroid.os.MessageQueue.next(MessageQueue.java:119)
  atandroid.os.Looper.loop(Looper.java:110)
 at android.app.ActivityThread.main(ActivityThread.java:3688)
 at java.lang.reflect.Method.invokeNative(Native Method)
  atjava.lang.reflect.Method.invoke(Method.java:507)
  atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
 at dalvik.system.NativeStart.main(Native Method)
说明主线程在等待下条消息进入消息队列


2.总结出如何解决ANR的一般步骤:

   (1)首先分析log

   (2)从trace.txt文件中查看调用track

   (3)仔细查看ANR的成因(iowait?block?memoryleak?)

  (4)结合分析结果,查看相关代码,找出出现问题的代码并修改验证。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值