ANR详解

1:

当用户点击屏幕时,系统会生成一个 MotionEvent 并回调相应 ViewonTouchEvent 方法。如果在 onTouchEvent 方法中执行耗时操作,会导致主线程的 Looper 被阻塞,无法及时处理接下来的事件或消息。如果这种阻塞持续超过 5 秒,系统会认为应用程序没有响应,从而触发 ANR(Application Not Responding)弹窗。

这种情况下,表现为在主线程处理当前触摸事件时,无法及时响应后续的用户点击操作或者其他通过 Handler 发送的消息。

为了避免 ANR,主线程(UI 线程)应该尽量避免执行耗时操作。当 LooperMessageQueue 中取出一个消息(Message)时,如果该消息需要进行耗时处理,应该将这些操作移到子线程中执行。这样可以确保主线程能够迅速处理下一个消息,保持应用的响应性,避免 ANR 弹窗的出现。

在 Android 中,可以使用 AsyncTaskHandlerThreadExecutorService 等工具将耗时操作移到后台线程中执行,同时通过 Handler 将结果传回主线程以更新 UI。这样可以有效避免主线程被阻塞,提高应用的流畅度和用户体验。

总结起来:

  1. ANR 触发原因:主线程被阻塞超过 5 秒,导致无法处理后续的事件或消息。
  2. 避免方法:将耗时操作移到后台线程,保持主线程的轻量级和高响应性。
  3. 实现工具:使用 AsyncTaskHandlerThreadExecutorService 等工具执行后台任务,通过 Handler 更新 UI。

通过这些措施,可以确保主线程快速响应用户输入和系统事件,从而避免 ANR 的发生。

 

ANR 触发机制

  1. 第一个输入事件

    • 用户产生第一个输入事件(例如,点击屏幕)。
    • 系统将该事件发送给应用并调用相应的处理方法(如 onTouchEvent)。
  2. 第二个输入事件

    • 用户产生第二个输入事件。
    • 系统记录第一个事件的处理时间是否超过 0.5 秒。
    • 如果第一个事件超过 0.5 秒还未处理完,系统会设置一个定时器,5 秒后触发检查。
  3. 定时器触发

    • 5 秒后,定时器触发,系统检查第一个事件是否已经处理完毕。
    • 如果第一个事件仍未处理完毕,系统认为应用没有响应,触发 ANR。

关键点

  • 第一个事件的处理时间:第一个输入事件必须在 5.5 秒以上(0.5 秒 + 5 秒定时器)没有被处理完成并反馈回系统。
  • 第二个输入事件的存在:需要有第二个输入事件产生,系统才能开始计时和触发 ANR。

本质分析

  • 第一个事件的阻塞:本质上,ANR 的触发是由于第一个事件在长时间内(5.5 秒以上)没有被处理完成。第二个事件的存在只是一个触发条件,用来启动定时器和后续的 ANR 机制。

  • 第二个事件的作用:第二个事件的主要作用是告诉系统第一个事件已经处理时间过长,从而开始计时。如果没有第二个事件,系统不会意识到第一个事件的处理时间过长,也就不会触发 ANR。

  • 主线程阻塞:如果主线程被一个耗时操作长时间阻塞,无论有多少输入事件,最终都会导致无法响应后续的输入事件,从而触发 ANR。

posted @ 2024-06-20 08:39  蜗牛攀爬  阅读(5)  评论(0编辑  收藏  举报