Android开发- Android ANR原因分析

1 ANR简介

ANR,全称是Application Not Responding,即应用程序无响应(不是Activity无响应)。当App在特定时间内无法响应屏幕触摸或键盘输入事件,或者特定事件没有处理完毕,就会发生ANR。

2 深入理解ANR:

2.1 特定时间:
        InputDispatching Timeout:5秒内无法响应屏幕触摸事件或键盘输入事件;
        BroadcastQueue Timeout :在执行前台广播(BroadcastReceiver)的onReceive()函数时10秒没有处理完成,后台为60秒;
        Service Timeout :前台服务20秒内,后台服务在200秒内没有执行完毕;
        ContentProvider Timeout :ContentProvider的publish在10s内没进行完; 

2.2 经常发生ANR的场景:

(1): 应用程序UI线程存在耗时操作, 如UI线程进行网络请求, 数据库操作或者文件操作, 这些耗时操作的情况都可能会导致UI线程无法及时处理用户的输入,导致ANR产生。

例如,这是一个主线程执行耗时操作的log:


(2):UI线程等待子线程释放一个锁,从而无法处理用户的请求输入;
(3):耗时操作的动画需要大量的计算工作, 导致CPU的负荷很重。

3. 如何避免ANR的发生:

尽量避免在主线程(UI线程)中作耗时操作。或者说,耗时操作尽可能在子线程中进行,而UI的更新一定得在主线程中(UI线程)进行。 

4. ANR的分析方法: 

主要考虑主线程的执行代码:

  1. 应用在主线程上非常缓慢地执行涉及 I/O 的操作。
  2. 应用在主线程上进行长时间的计算。
  3. 主线程在对另一个进程进行同步 binder 调用,而后者需要很长时间才能返回。
  4. 主线程处于阻塞状态,为发生在另一个线程上的长操作等待同步的块。
  5. 主线程在进程中或通过 binder 调用与另一个线程之间发生死锁。主线程不只是在等待长操作执行完毕,而且处于死锁状态。

分析方法:

4.1 通过log来分析:
   用logcat可以清晰的看到ANR发生的时机(见“5 ANR举例”);

 4.2 查看traces.txt:
    ANR发生,通常,系统会将相关信息写入到traces.txt文件中,即“/data/anr/traces.txt”文件。我们可以通过分析这个文件,从而定位ANR发生时的场景;

adb root
adb shell ls /data/anr
adb pull /data/anr/traces.txt

4.3 通过traceview等工具来分析:
   入下图(traceview):

分析:

上图中,耗时代码都在子线程AsyncTask中进行,所以不会发生ANR。 如果main中有大面积的红色区域块,说明在主线程中有耗时操作,就有ke能发生ANR。

5 ANR举例:

分析如下代码:

btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        try {
            Thread.sleep(100000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});

分析:

在主线程中,用sleep来模拟耗时操作。 

运行程序log如下:

2014-10-12 11:12:23.612 3105-3180/system_process E/ActivityManager: ANR in com.example.app1 (com.example.app1/.MainActivity)
    PID: 19534
    Reason: Input dispatching timed out 

(com.example.app1/com.example.app1.MainActivity, Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago.  Wait queue length: 2.  Wait queue head age: 8602.5ms.)
    Parent: com.example.app1/.MainActivity
    Load: 7.01 / 6.89 / 6.74
CPU usage from 0ms to 6142ms later (2014-10-12 11:12:17.718 to 2014-10-12 11:12:23.811):
      16% 3105/system_server: 7.9% user + 8.1% kernel / faults: 6549 minor


      0.3% 2779/media.codec: 0.2% user + 0% kernel / faults: 35716 minor
      10% 763/surfaceflinger: 8.2% user + 2.6% kernel / faults: 419 minor
    ...
     
      0.1% 27263/kworker/4:2: 0% user + 0.1% kernel
      0.1% 27743/kworker/0:0: 0% user + 0.1% kernel
    15% TOTAL: 10% user + 5.4% kernel + 0.1% iowait + 0.2% irq + 0% softirq

说明:

很明显,发生了ANR,而且,在log中,也能看到具体发生ANR的类名,方法名,进程ID,原因等信息。该例中的这些信息是:

ANR in com.example.app1 (com.example.app1/.MainActivity)
    PID: 19534
    Reason: Input dispatching timed out  

6 ANR源码调用:

只有发生ANR,那么,AppNotRespondingDialog.show();就会被调用:

AppNotRespondingDialog.show();

在ActivityManagerService,有如下代码:

case SHOW_NOT_RESPONDING_MSG: {

    ......

    Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
                                mContext, proc,
                   (ActivityRecord)data.get("activity"));
    d.show();
    proc.anrDialog = d;

    ......

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值