Android之ANR(Application Not Responding)

注意:本篇文章是本人阅读相关文章所写下的总结,方便以后查阅,所有内容非原创,侵权删。

本篇文章内容来自于:
Android高级进阶 顾浩鑫
Android ANR产生的原因以及其定位分析

目录

  1. 什么是ANR
  2. ANR产生的原因
  3. 典型的ANR问题场景
  4. ANR发生了 如何定位和分析
  5. ANR的避免和检测
    --5.1 StrictMode
    --5.2 BlockCanary

1. 什么是ANR

ANR:Application Not Responding。
ANR的直观体验是用户在操作APP的过程中,感觉界面卡顿,当卡顿时间超过一定时间(一般5s)就会出现ANR对话框。

2. ANR产生的原因

主要是因为我们在主线程中做了太多的耗时操作。
超时产生原因一般有2种:

  1. 当前的事件没有机会得到处理。
    例如UI线程正在响应另外一个事件,当前事件由于某种原因被阻塞了。
  2. 当前事件正在处理,但是由于耗时太长没能及时完成。

根据ANR产生的原因不同,超时时间也不尽相同。
从本质上讲产生ANR的原因有3种:
大致可以对应到Android四大组件中的三个(Activity/View、BroadcastReceiver、Service)

  1. KeyDispatchTimeout
    最常见的一种类型,原因是view的按键事件或者触摸事件在特定的时间(5s)内无法得到响应。
  2. BroadCastTimeout
    原因是BroadCastReceiver的onReceive()函数运行在主线程,在特定的时间(10s)内无法完成处理。
  3. ServiceTimeout
    比较少出现的一种类型,原因是Service的各个生命周期函数在特定时间(20s)内无法完成处理。

3. 典型的ANR问题场景

  • 应用程序UI线程存在耗时操作。
    例如在UI线程中进行网络请求,数据库操作或者文件操作等,可能会导致UI线程无法及时处理用户输入等。
    在Android4.0之后,如果在UI线程中进行网络操作,将会抛出NetworkOnMainThreadException异常。
  • 应用程序的UI线程等待子线程释放某个锁,从而无法处理用户的输入。
  • 耗时的动画需要大量的计算工作,可能导致CPU负载过重。

4. ANR发生了 如何定位和分析

当发生ANR时,可通过结合logcat日志和生成的位于手机内部存储的/data/anr/traces.txt文件进行分析和定位。

5. ANR的避免和检测

5.1 StrictMode

严格模式StrictMode是Android SDK提供的一个用来检测代码中是否存在违规操作的工具类。
主要用于检测两大类问题:(1)可能存在的主线程耗时操作 (2)是否发生泄漏

  • 线程策略 ThreadPolicy
    --detectCustomSlowCalls:检测自定义耗时操作
    --detectDiskReads:检测是否存在磁盘读取操作
    --detectDiskWrites:检测是否存在磁盘写入操作
    --detectNetwork:检测是否存在网络操作
  • 虚拟机策略 VmPolicy
    --detectActivityLeaks:检测是否存在Activity泄漏
    --detectLeakedClosableObjects:检测是否存在未关闭的Closable对象泄漏
    --detectLeakedSqliteObjects:检测是否存在Sqlite对象泄漏
    --setClassInstanceLimit:检测类实例个数是否超过限制

只能在Debug版本使用它,发不到市场上的版本要关掉。
使用
只需要在应用初始化的地方例如Application或者MainActivity的onCreate方法中执行代码:

        if (BuildConfig.DEBUG) {
            //===开启线程模式===
            //开启全部
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
            //开启部分
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
            //===开启虚拟机模式===
            //开启全部
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
            //开启部分
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectActivityLeaks().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().build());
        }

5.2 BlockCanary

github地址

你可能感兴趣的:(Android之ANR(Application Not Responding))