• [转发]Android 系统稳定性


    文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任。
    很久之前写的了,留着有点浪费,共享之。
    编写者:李文栋 

    http://rayleeya.iteye.com/blog/1955652

            如果你是一个Android应用程序开发人员,你的人生中不可避免的三件事情是:死亡、缴税和ANR。这么说是夸张了,但是由于Android本身的设计,以及应用程序和系统在开发过程中的缺陷,经常会在测试过程中遇到各种各样的ANR问题。在功能性的测试中还少一些,主要是在压力测试中(例如Monkey测试)会遇到非常多的ANR问题。本章的目的就是汇总笔者在工作中遇到的各种ANR问题,将其归纳总结出一套分析和处理ANR问题的方法,希望能够通过这套方法为大家提供思路,有效的减少大家处理ANR问题的时间。同时也会给出一些避免ANR的最佳实践,更多的从预防做起,更少的做事后补救。

    考虑到看本文的读者大多是有实际经验的开发人员,我会尽量少的提到一些基础的概念,我也希望给大家更多的“干货”。

     

            本章的主要内容如下:

    1. ANR简介(什么是ANR、为什么会有ANR、ANR的异常长什么样)

    2. 如何分析ANR(引起ANR的原因分类、分析ANR的利器)

    3. 实例讲解

    4. 避免ANR的最佳实践(从错误中吸取教训)

    1.1 ANR简介

            ANR,是“Application Not Responding”的缩写,即“应用程序无响应”。在Android中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会监测应用程序的响应时间,如果应用程序主线程(即UI线程)在超时时间内对输入事件没有处理完毕,或者对特定操作没有执行完毕,就会出现ANR。对于输入事件没有处理完毕产生的ANR,Android会显示一个对话框,提示用户当前应用程序没有响应,用户可以选择继续等待或者关闭这个应用程序(也就是杀掉这个应用程序的进程)。



    1.1.1 为什么会有ANR

            如上所述,ANR的产生需要同时满足三个条件:

    • 主线程:只有应用程序进程的主线程响应超时才会产生ANR;

    • 超时时间:产生ANR的上下文不同,超时时间也会不同,但只要在这个时间上限内没有响应就会ANR;

    • 输入事件/特定操作:输入事件是指按键、触屏等设备输入事件,特定操作是指BroadcastReceiver和Service的生命周期中的各个函数,产生ANR的上下文不同,导致ANR的原因也会不同;

            针对这三个条件,有以下三种情况会触发ANR,详细说明如下。

    1. 主线程对输入事件在5秒内没有处理完毕

            Android的事件系统从2.3开始做了完全不同的实现,原先2.2中是在Java层实现的,但在2.3中整体转移到了C++层,本书基于2.3以后的版本进行说明。我们先简单了解一下产生这种ANR的整个流程<!-- 在这章之前要先讲Android的事件机制?还是放在后一章讲?偏向于放在后面。 -->。

    当应用程序的Window处于Active状态并且能够接收输入事件(例如按键事件、触摸事件等)时,系统底层上报的事件就会被InputDispatcher分发给这个应用程序,应用程序的主线程通过InputChannel读取输入事件并交给界面视图处理,界面视图是一个树状结构,DecorView是视图树的根,事件从树根开始一层一层向端点(例如一个Button)传递。我们通常会注册一个监听器来接收并处理事件,或者创建自定义的视图控件来处理事件。

            InputDispatcher运行在系统进程(进程名为system_server)的一个单独的线程中,应用程序的主线程在处理事件的过程中,InputDispatcher会不断的检测处理过程是否超时,一旦超时,会通过一系列的回调通知WMS的notifyANR函数,最终会调用到AMS中mHandler对象里的SHOW_NOT_RESPONDING_MSG这个case,此时界面上就显示系统提示对话框了,同时使用logcat命令查看log(日志信息)也可以看到关于ANR的信息。InputDispatcher就是那个爱打“小报告”的家伙。

     

            一下子出现了好几个重要的名词,要深入了解这种情况的ANR,需要熟悉Android的事件机制,本书会在别的章节中详细分析,这里只需要记住他们的功能:

    • Window:具体指的是PhoneWindow对象,表示一个能够显示的窗口,它能够接收系统分发的各种输入事件;

    • InputDispatcher:将系统上报的输入事件分发给当前活动的窗口;

    • InputChannel:InputDispatcher和应用程序分别运行在两个不同的进程中,InputDispatcher就是通过InputChannel将事件对象传递给应用进程的。



    注意:产生这种ANR的前提是要有输入事件,如果用户没有触发任何输入事件,即便是主线程阻塞了,也不会产生ANR,因为InputDispatcher没有分发事件给应用程序,当然也不会检测处理超时和报告ANR了。



    1. 主线程在执行BroadcastReceiveronReceive函数时10秒内没有执行完毕

            BroadcastReceiver(简称BR)的onReceive函数运行在主线程中,当这个函数超过10秒钟没有返回就会触发ANR。不过对这种情况的ANR系统不会显示对话框提示,仅是输出log而已。



    1. 主线程在执行Service的各个生命周期函数时20秒内没有执行完毕

            Service的各个生命周期函数也运行在主线程中,当这些函数超过20秒钟没有返回就会触发ANR。同样对这种情况的ANR系统也不会显示对话框提示,仅是输出log。

     

    三种ANR中只有第1种会显示系统提示对话框,因为用户正在做界面交互操作,如果长时间没有任何响应,会让用户怀疑设备死机了,大多数人此时会开始乱按,甚至拔出电池重启,给用户的体验肯定是非常糟糕的。

            三种ANR发生时都会在log中输出错误信息,你会发现各个应用进程和系统进程的函数堆栈信息都输出到了一个/data/anr/traces.txt的文件中,这个文件是分析ANR原因的关键文件,同时在日志中还会看到当时的CPU使用率,这也是重要信息,在后面的章节会详细介绍如何利用它们分析ANR问题。

    这三种ANR不是孤立的,有可能会相互影响。例如一个应用程序进程中同时有一个正在显示的Activity和一个正在处理消息的BroadcastReceiver,它们都运行在这个进程的主线程中。如果BR的onReceive函数没有返回,此时用户点击屏幕,而onReceive超过5秒仍然没有返回,主线程无法处理用户输入事件,就会引起第1种ANR。如果继续超过10秒没有返回,又会引起第2种ANR。

  • 相关阅读:
    2021NUAA暑假集训 Day3 题解
    2021NUAA暑假集训 Day2 题解
    2021NUAA暑期模拟赛部分题解
    CodeForces 1038D Slime
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 10689 Yet another Number Sequence
    HDU 4549 M斐波那契数列
    HDU 4990 Reading comprehension
    CodeForces 450B Jzzhu and Sequences
  • 原文地址:https://www.cnblogs.com/jefree/p/4433867.html
Copyright © 2020-2023  润新知