Android Looper is delaying message dispatch due to FrameHandler

1.7k views Asked by At

The application that I'm working on is receiving data at a very high rate (every 100ms). The data is received by the background thread and I need to display it on the activity.

I am using handler to post data from the background thread to main thread. But after some time we start to see the delay.

Delay

The background thread is receiving and posting data to handler at 100ms interval. But the main thread looper get busy in waiting for FrameHandler to finish its job. Due to which my messages gets processed with delay. And this delay keeps increasing.

Below are the looper log:

com.example.app.MainActivity$4 - is my app's custom handler

android.view.Choreographer$FrameHandler - OS frame handler

09-08 14:52:02.465 15397 15397 D MAIN_LOOPER: >>>>> Dispatching to Handler (com.example.app.MainActivity$4) {3b4862a} null: 102

09-08 14:52:02.467 15397 15397 D MAIN_LOOPER: <<<<< Finished to Handler (com.example.app.MainActivity$4) {3b4862a} null

My app took 2ms to progress a data

09-08 14:52:02.467 15397 15397 D MAIN_LOOPER: >>>>> Dispatching to Handler (android.view.Choreographer$FrameHandler) {6eab416} android.view.Choreographer$FrameDisplayEventReceiver@3d19197: 0

09-08 14:52:06.080 15397 15397 D MAIN_LOOPER: <<<<< Finished to Handler (android.view.Choreographer$FrameHandler) {6eab416} android.view.Choreographer$FrameDisplayEventReceiver@3d19197

FrameHandler took 4 secs to finish processing.

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

09-08 14:52:06.083 15397 15397 D MAIN_LOOPER: <<<<< Finished to Handler (com.example.app.MainActivity$4) {3b4862a} null

How can we reduce the time taken by frame handler or any alternative to post data from background thread to main thread?

2

There are 2 answers

3
Drivers Sea On

Not seeing your code, I can only take a guess. I do not think you will like my guess, however, it is likely true. If you are checking for data every 10th of a second, it is likely that android identifies this and says this is pointless and slows the app down. Another possibility is the fact you might have to wait for the code trying to receive the data to take over 10th of a second and this would slow the whole thread down.

Take it for what it is, a guess.

0
Fco P. On

Is hard to propose alternatives without seeing your code, but the explanation itself is simple. You are over-stressing the choreographer. The main thread handler processes their message queue every time there's an screen update. But you trigger screen changes, so more updates. At some points, the amount of work to be done before the next frame is too much, and some frames gets skipped. So then next messages are delayed, and more messages are coming, getting more delay... you get the idea.

If you can't alter either the frequency of the messages, or the amount of messages, I would suggest to take them out of the choreographer. Encapsulate your code into a class, with a callback to perform the UI updates, and instantiate it (or set the callback) from the activity, using runOnUIThread(), so you can skip the queue:

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

An event bus may help with the event delivery. If you are updating a recyclerView, direct access to the adapter data may work as well. As I said, it depends on what you are actually doing.