В каком потоке работает Runnable?

Я хочу обновлять пользовательский интерфейс каждые 100 мс. После поиска в StackOverflow я нашел решение с использованием Runnable и Handler вот так

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

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

Оно работает! Но у меня есть несколько вопросов:

  1. В каком потоке работает этот Runnable? MainThread или другой поток? Вот документы о postDelay введите здесь описание изображения

Handler подключен к MainThread, поэтому Runnable работает в MainThread?

  1. Если Runnable работает в MainThread, зачем нужен Handler? Насколько мне известно, Handler используется для отправки сообщений между двумя потоками.

person Qk Lahpita    schedule 06.12.2017    source источник


Ответы (3)


В каком потоке работает этот Runnable?

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

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

Этот Runnable выполняется в текущем потоке, то есть в потоке, который вызывает этот код. Он не создает и не создает волшебным образом другой поток. Runnable.run() - это только вызов метода.

Последующие выполнения этого потока Handler в любом потоке, в котором выполняется Handler, по сути ничего не делают, кроме как перепланируют себя. Трудно поверить, что это решение чего-либо.

person user207421    schedule 06.12.2017

Обработчик подключен к MainThread, поэтому Runnable работает в MainThread?

Из документации Handler:

Каждый экземпляр Handler связан с одним потоком и очередью сообщений этого потока. Когда вы создаете новый обработчик, он привязывается к потоку/очереди сообщений потока, который его создает — с этого момента он будет доставлять сообщения и исполняемые объекты в эту очередь сообщений и выполнять их по мере их выхода из сообщения. очередь.

Если вы хотите запустить Runnable в другом потоке, вы можете использовать HandlerThread .

Связанный пост:

Зачем использовать HandlerThread в Android

Если Runnable работает на MainThread, зачем нужен обработчик? Насколько мне известно, Handler используется для отправки сообщений между двумя потоками.

Есть два основных варианта использования обработчика:

  1. Чтобы запланировать выполнение сообщений и исполняемых модулей в какой-то момент в будущем.
  2. Поставить в очередь действие, которое будет выполняться в потоке, отличном от вашего собственного.

Если вы используете только MainThread, Handler полезно отправлять сообщения в какой-то момент в будущем. Если вы используете разные потоки, Handler полезно для связи между потоками.

person Ravindra babu    schedule 06.12.2017

В вашем примере Runnable работает в потоке пользовательского интерфейса.

Если вы хотите, чтобы ваш Handler и все его Runnable работали в другом потоке, вам придется назначить его новым HandlerThread Looper.

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

Затем вы можете передать экземпляр Runnable через postDelayed(Runnable, long).

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

handler.postDelayed(r, 0);
person Marko Pacak    schedule 06.12.2017
comment
Не в первый раз. - person user207421; 06.12.2017
comment
@EJP, ты имеешь в виду не звонить postDelayed в первый раз? - person Marko Pacak; 06.12.2017
comment
runnable.run() сначала вызывается текущим потоком. В следующий раз и после этого он вызывается Handler. Не в первый раз. - person user207421; 06.12.2017
comment
@pskink Утверждение «в вашем примере Runnable работает в потоке пользовательского интерфейса», и мой комментарий относятся к коду OP, о чем на самом деле и идет речь. - person user207421; 06.12.2017
comment
@EJP первое выполнение Runnable вызывается Handler. С самого начала вы работаете в отдельном потоке,... - person Marko Pacak; 06.12.2017
comment
@payloc Последняя строка кода OP - runnable.run(), она вызывается текущим потоком и не имеет ничего общего с Handler. - person user207421; 06.12.2017
comment
@pskink Я могу только предложить вам перечитать вопрос. Это там в черно-белом. Я копирую/вставляю, если оттуда, в свой собственный ответ. - person user207421; 06.12.2017
comment
@pskink Это действительно так, когда вы продолжаете делать контрфактические заявления, игнорируя свидетельства ваших собственных глаз. runnable.run(); находится там черным по белому в вопросе ОП, откуда я только что скопировал/вставил его снова. - person user207421; 06.12.2017
comment
@pskink Очевидно, вы действительно не можете. runnable.run() (a) присутствует в коде OP и (b) выполняется в текущем потоке. Нет двух способов об этом. - person user207421; 07.12.2017