7

I want to update UI every 100ms. After searching in StackOverflow, I found a solution using Runnable and Handler like this

final Handler handler = new Handler();
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        //update UI here

        handler.postDelayed(this, 100);
    }
};
runnable.run();

It works! But I have some questions:

  1. Which thread does this Runnable run on? MainThread or another thread? Here is the docs about postDelay enter image description here

Handler is attached MainThread, so is Runnable running on MainThread?

  1. If Runnable is running on MainThread, why needs Handler? According to my knowledge, Handler is used to send messages between two threads
Qk Lahpita
  • 427
  • 2
  • 10
  • 18

2 Answers2

7

Which thread does this Runnable run on?

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        //update UI here

        handler.postDelayed(this, 100);
    }
};
runnable.run()

This Runnable runs on the current thread, i.e. the thread that invokes this code. It doesn't magically create, or constitute, another thread. Runnable.run() is only a method call.

The subsequent executions of this thread, by the Handler, in whatever thread the Handler runs in, do essentially nothing except reschedule themselves. It's hard to believe this is a solution to anything.

user207421
  • 305,947
  • 44
  • 307
  • 483
1

In your example, the Runnable runs on the UI Thread.

If you want your Handler and all its Runnable to run in a different Thread, you'll have to assign it a a new HandlerThread's Looper.

final HandlerThread handlerThread = new HandlerThread(MY_THREAD_ID);
handlerThread.start();
final Handler handler = new Handler(handlerThread.getLooper());

You can then pass the Runnable instance via postDelayed(Runnable, long).

Runnable r = new Runnable() {
    @Override public void run() {
        handler.postDelayed(this, 2000);
    }   
};

handler.postDelayed(r, 0);
payloc91
  • 3,724
  • 1
  • 17
  • 45
  • Not the first time. – user207421 Dec 06 '17 at 09:05
  • @EJP you mean not to call `postDelayed` the first time? – payloc91 Dec 06 '17 at 09:06
  • `runnable.run()` is first invoked by the current thread. Next time and thereafter it is invoked by the `Handler`. Not the first time. – user207421 Dec 06 '17 at 09:08
  • @pskink The statement 'in your example, the `Runnable` runs on the UI Thread' and my comment both refer to the OP's code, which is what the question is actually about. – user207421 Dec 06 '17 at 09:11
  • @EJP the first `Runnable` execution is invoked by the `Handler`. From the beginning, you are running on a separate thread, ... – payloc91 Dec 06 '17 at 09:13
  • @payloc The final line of the OP's code is `runnable.run()`, and it is invoked by the current thread, and it has exactly nothing to do with the `Handler` whatsoever. – user207421 Dec 06 '17 at 09:14
  • @pskink I can only suggest you re-read the question. It's up there in black and white. I copy/pasted if from there into my own answer. – user207421 Dec 06 '17 at 09:15
  • @pskink It is indeed, when you keep making counterfactual claims in defiance of the evidence of your own eyes. `runnable.run();` is up there in black and white in the OP's question, from where I have just copy/pasted it *again*. – user207421 Dec 06 '17 at 09:16
  • @pskink Evidently you can't indeed. `runnable.run()` (a) is present in the OP's code and (b) runs in the current thread. No two ways about it. – user207421 Dec 06 '17 at 22:50