【问题标题】:Android Looper is delaying message dispatch due to FrameHandler由于 FrameHandler,Android Looper 正在延迟消息发送
【发布时间】:2021-11-08 12:55:03
【问题描述】:

我正在处理的应用程序正在以非常高的速率(每 100 毫秒)接收数据。数据由后台线程接收,我需要将其显示在 Activity 上。

我正在使用处理程序将数据从后台线程发布到主线程。但一段时间后,我们开始看到延迟。

延迟

后台线程以 100 毫秒的间隔接收数据并将数据发送到处理程序。但是主线程循环器忙于等待 FrameHandler 完成它的工作。因此,我的消息被延迟处理。而且这种延迟不断增加。

以下是looper日志:

com.example.app.MainActivity$4 - 是我应用的自定义处理程序

android.view.Choreographer$FrameHandler - 操作系统帧处理程序

09-08 14:52:02.465 15397 15397 D MAIN_LOOPER: >>>> 调度到处理程序 (com.example.app.MainActivity$4) {3b4862a} null: 102

09-08 14:52:02.467 15397 15397 D MAIN_LOOPER:

我的应用需要 2 毫秒来处理数据

09-08 14:52:02.467 15397 15397 D MAIN_LOOPER: >>>>> 调度到处理程序 (android.view.Choreographer$FrameHandler) {6eab416} android.view.Choreographer$FrameDisplayEventReceiver@3d19197: 0

09-08 14:52:06.080 15397 15397 D MAIN_LOOPER:

FrameHandler 用了 4 秒完成处理。

09-08 14:52:06.080 15397 15397 D MAIN_LOOPER: >>>> 调度到 Handler (com.example.app.MainActivity$4) {3b4862a} null: 102

09-08 14:52:06.083 15397 15397 D MAIN_LOOPER:

我们如何减少帧处理程序或任何替代方法将数据从后台线程发布到主线程所花费的时间?

【问题讨论】:

  • 你使用什么 API 来做 bg 工作?是服务还是线程还是workManager?
  • 这是一项服务。服务在后台线程上下文中从其他源接收一些数据。
  • 您是否尝试过使用允许 MVVM 模式的android architecture components,您可以在后台线程上工作并将更改发布到一组LiveData,任何观察者都会收到更改通知?
  • 我也试过这个,行为是一样的。

标签: java android handler android-looper


【解决方案1】:

没有看到你的代码很难提出替代方案,但解释本身很简单。你对编舞的压力太大了。每次有屏幕更新时,主线程处理程序都会处理他们的消息队列。但是您会触发屏幕更改,因此会进行更多更新。在某些时候,下一帧之前要完成的工作量太多,有些帧会被跳过。所以接下来的消息被延迟了,更多的消息来了,越来越多的延迟......你明白了。

如果您无法更改消息的频率或消息的数量,我建议您将它们从编舞者那里取出。将您的代码封装到一个类中,使用回调来执行 UI 更新,并使用 runOnUIThread() 从活动中实例化它(或设置回调),这样您就可以跳过队列:

public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

事件总线可能有助于事件传递。如果您正在更新 recyclerView,那么直接访问适配器数据也可以。正如我所说,这取决于您实际在做什么。

【讨论】:

    【解决方案2】:

    没有看到你的代码,我只能猜测。我不认为你会喜欢我的猜测,但是,它很可能是真的。如果您每 10 秒检查一次数据,则 android 很可能会识别到这一点并说这是毫无意义的,并且会减慢应用程序的速度。另一种可能性是您可能必须等待尝试接收数据的代码占用超过 10 秒的时间,这会减慢整个线程的速度。

    猜一猜。

    【讨论】:

    • 我没有检查数据,我的服务以固定速率将数据发布到处理程序,但由于帧处理程序,循环器无法将数据分派到目标处理程序。
    • 处理程序发布的确切内容是什么?您每 100 毫秒执行什么样的 UI 更改。如果不看到句子的“this”部分,就很难调试“this is slow”。
    • 数据包含各种属性的开/关状态,UI更改是根据接收到的数据的开/关状态进行简单的图像更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    相关资源
    最近更新 更多