📜  什么是ANR?如何在Android中防止ANR?

📅  最后修改于: 2021-05-10 14:31:27             🧑  作者: Mango

ANR代表应用程序无响应。如果您正在UI线程上运行一个进程,而该过程需要花费较长的时间(通常为5秒左右),则会发生ANR。在此期间,GUI(图形用户界面)将锁定,最终可能会导致用户不执行任何操作。大约5秒钟后。发生后,如果线程仍未恢复,则会显示一个ANR对话框,通知用户设备未响应,并可以让用户选择等待,以希望应用最终恢复,或者强制关闭应用程序。这就是ANR对话框显示给用户的方式。

向用户显示的ANR对话框

崩溃是指在应用内引发了未处理的异常。例如,如果您尝试设置EditText组件文本但是EditText为null,并且没有try-catch语句来捕获异常,则您的应用程序将崩溃并可以被强制关闭。用户将不会看到导致崩溃的原因,将向他们显示一个对话框,告诉您该应用已意外强制关闭,并可以选择发送错误报告。例如,由Java.lang.NullPointerException引起的错误是ANR。当在“主”线程中进行一些长时间的操作时,就会发生ANR。这是事件循环线程,如果很忙,Android将无法处理应用程序中的任何GUI事件,因此会显示一个ANR对话框。现在,在您发布的跟踪中,大多数线程似乎运行良好,没有问题。它在MessageQueue中处于空闲状态,希望返回另一条消息。在您的情况下,ANR可能是一个较长的操作,而不是永久性地阻塞线程的操作,因此事件线程在操作完成后恢复,并且跟踪在ANR之后进行。

如何预防ANR?

停止在主线程上执行繁重的任务。而是简单地使用工作线程,例如IntentService,AsyncTask Handler或另一个线程。如果它是一个永久性的块(例如,死锁获取了一些锁),则检测ANR发生的位置很简单,但是如果只是短暂的延迟,则很难检测。首先,重新评估您的代码和外观以发现易受攻击的位置和长期运行的操作。示例可能包括使用事件线程内部的套接字,锁,线程睡眠和其他阻止操作。您应该确保所有这些操作都在单独的线程中进行。如果没有问题,请使用DDMS并启用线程视图。这显示了应用程序中的所有线程,与您拥有的跟踪类似。再现ANR,并在相同的时间刷新最多的线程。那应该向您确切显示ANR发生时的情况。当以下情况之一发生时,将为您的应用触发ANR:

  1. 当您的活动处于前台状态时,您的应用在5秒钟内没有输入事件或BroadcastReceiver(例如按键或屏幕触摸事件)。
  2. 当您不在前台进行活动时,您的BroadcastReceiver并没有在相当长的时间内完成执行。

如果您的应用遇到ANR,您将在本文中使用该指南来诊断和解决此问题。

Android要点

当您的应用程序展示出过多的ANR时,Android生命体可以通过Play控制台提醒您,从而帮助您提高应用程序的性能。在以下情况下,Android vitals认为ANR过多:

  1. 在每天最少0.47%的日常活动中展示至少一个ANR。
  2. 至少在每日课程的0.24%中显示2个或更多ANR。
  3. 至少在每日课程的0.17%内展示3个或更多ANR。
  4. 每天至少展示0.13%的3个或更多ANR。

诊断ANR

由于Android界面提供了有效的ANR删除工具,因此可以轻松解决ANR!查找它们可能包括(但不限于):

  1. 该应用程序正在执行缓慢的操作,其中涉及操作系统的I / O操作。
  2. 主线程正在对另一个进程进行同步联编程序调用,另一个进程正在花费较长的时间才能返回。
  3. 在您的进程中或通过活页夹调用,主线程与另一个线程处于死锁状态。大多数线程不仅希望扩展操作结束,而且还处于死锁状态。
  4. 该应用程序正在基本线程上进行扩展计算。

使用Android严格模式(API级别> 9)

使用StrictMode启动API Level 9将有助于您在开发应用程序时在大多数线程上发现某些意外的I / O操作。您将在设备或活动级别使用StrictMode。在此处阅读有关如何使用StrictMode的更多信息。

此外,您还可以通过从Android ADB中提取跟踪文件来找到有关ANR的信息,如下所示:

adb root
adb shell ls /data/anr
adb pull /data/anr/

但是,如果您的用户仍在遇到ANR,则一定要在Android设备监控器中检出主aka主线程的状态。通常,如果主线程准备好更新UI,则它处于RUNNABLE状态;如果一切正常,它通常会做出响应!

一个例子

Java
@Override
public void onClick(View view) {
    // This task works on the 
    // main thread and will cause an ANR.
    MergeSort.sort(data);
}


在上述情况下,我们需要做的是从主线程中删除排序过程,并将其放入另一个类或线程中,以便系统可以异步处理它。

小费

当发生ANR且您的应用突然崩溃时,Android Studio会在设备本身的txt文件中记录一些与案例有关的信息。您可以使用ADB收集日志并进行查看。您还可以从Firebase中添加Crashlytics,以在应用程序中出现ANR时抓住它们,并获得它们的出现频率,并在发生事件的活动线程中发生事件!通过访问此处查看有关ANR的更多详细信息。

想要一个节奏更快,更具竞争性的环境来学习Android的基础知识吗?
单击此处前往由我们的专家精心策划的指南,以使您立即做好行业准备!