当前位置:   article > 正文

Android开发- Android ANR原因分析_input dispatching timed out

input dispatching timed out

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发生时的场景;

  1. adb root
  2. adb shell ls /data/anr
  3. adb pull /data/anr/traces.txt

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

分析:

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

5 ANR举例:

分析如下代码:

  1. btn.setOnClickListener(new View.OnClickListener() {
  2. @Override
  3. public void onClick(View v) {
  4. try {
  5. Thread.sleep(100000);
  6. } catch (InterruptedException e) {
  7. e.printStackTrace();
  8. }
  9. }
  10. });

分析:

在主线程中,用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,有如下代码:

  1. case SHOW_NOT_RESPONDING_MSG: {
  2. ......
  3. Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
  4. mContext, proc,
  5. (ActivityRecord)data.get("activity"));
  6. d.show();
  7. proc.anrDialog = d;
  8. ......
  9. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号