Когда использовать handler.post() и когда использовать новый Thread()

Мне интересно, когда я должен использовать handler.post(runnable); и когда я должен использовать new Thread(runnable).start();

Это упоминается в документации разработчиков для Handler:

Вызывает добавление Runnable r в очередь сообщений. Runnable будет запущен в потоке, к которому прикреплен этот обработчик.

Означает ли это, что если я напишу в классе onCreate() of Activity:

Handler handler = new Handler();
handler.post(runnable);

тогда runnable будет вызываться в отдельном потоке или в потоке Activity?


person reiley    schedule 28.02.2013    source источник
comment
Никогда не используйте new Thread(runnable).start(), у вас может закончиться размер памяти стека VM. Вы хотите использовать Executors и сохранить ссылку на это (не создавайте нового исполнителя для каждого вызова, который перешел бы в фоновый поток)   -  person EpicPandaForce    schedule 10.03.2019


Ответы (4)


Вы должны использовать Handler.post() всякий раз, когда хотите выполнять операции в потоке пользовательского интерфейса.

Допустим, вы хотите изменить текст TextView в обратном вызове. Поскольку обратный вызов не выполняется в потоке пользовательского интерфейса, вы должны использовать Handler.post().

В Android, как и во многих других средах пользовательского интерфейса, элементы пользовательского интерфейса (виджеты) можно изменять только из потока пользовательского интерфейса.

Также обратите внимание, что термины «поток пользовательского интерфейса» и «основной поток» часто используются взаимозаменяемо.


Изменить: пример длительной задачи:

mHandler = new Handler();

new Thread(new Runnable() {
  @Override
  public void run () {
    // Perform long-running task here
    // (like audio buffering).
    // You may want to update a progress
    // bar every second, so use a handler:
    mHandler.post(new Runnable() {
     @Override
     public void run () {
       // make operation on the UI - for example
       // on a progress bar.
     }
    });
  }
}).start();

Конечно, если задача, которую вы хотите выполнить, очень длинная и существует риск того, что пользователь может тем временем переключиться на какое-то другое приложение, вам следует рассмотреть возможность использования Сервис.

person kamituel    schedule 28.02.2013
comment
Но если я хочу буферизовать аудиопоток из Интернета. Должен ли я сделать это через handler.post или с помощью нового потока? - person reiley; 28.02.2013
comment
На самом деле зависит от ваших требований. Я бы рассмотрел либо новый поток, либо службу. Я обновлю ответ примером через секунду. - person kamituel; 28.02.2013
comment
Объяснение неверно на многих уровнях. – Т.Димитров? Действительно? Абсолютно бездоказательный и бесполезный комментарий. Где ваши доказательства? - person Stanly T; 26.02.2019
comment
@T.Dimitrov, возможно, вы захотите более четко указать, что именно не так с объяснением здесь, иначе никто не узнает, что вы имеете в виду. - person EpicPandaForce; 10.03.2019
comment
Этот кодовый блок остается таким элегантным объяснением даже спустя 13 лет. - person Richard Le Mesurier; 18.08.2020
comment
Спасибо @RichardLeMesurier. Тем не менее, я почти уверен, что 2013 год был чуть меньше 13 лет назад ;) - person kamituel; 18.08.2020
comment
@kamituel действительно это ха-ха :-) Долгий рабочий день - мое единственное оправдание этому. Но все равно отличный ответ - person Richard Le Mesurier; 20.08.2020
comment
@kamituel, основываясь на этом ответе, означает ли это, что поток пользовательского интерфейса использует внутренний цикл событий (аналогичный асинхронному программированию в JavaScript)? Насколько я понимаю, похоже, что Handler.post в основном ставит в очередь событие в основном цикле событий потоков. - person h0r53; 19.07.2021

Чтобы ответить на ваш конкретный вопрос:

Означает ли это, что если в классе onCreate of Activity я напишу:

Обработчик обработчика = новый обработчик() hanlder.post(runnable); тогда runnable будет вызываться в отдельном потоке или в потоке Activity?

Нет, не будет. Runnable будет вызываться в самом основном потоке. Обработчик просто используется для публикации сообщения в потоке, к которому оно прикреплено (где оно создано). Он не создает поток сам по себе. В вашем примере вы создали обработчик в основном потоке (тот, где вызывается Activity.OnCreate()), и, следовательно, любое сообщение, размещенное в таком обработчике, будет выполняться только в основном потоке.

person pareshgoel    schedule 07.03.2014
comment
Правильные ответы не всегда выбираются как лучшие. Спасибо - person Natan Lotério; 25.07.2017
comment
Вы только что полностью изменили производительность моего приложения! Переход от обработчика к потоку только что заставил мое приложение летать! Так что большое спасибо человек!! - person hzitoun; 27.11.2017

Пример поднят:

mHandler = new Handler();
new Thread(new Runnable(){
  @Override
  public void run () {
    mHandler.post(new Runnable() {
     @Override
     public void run () {
       mUiView.setX(x);
     }
    });
  }
}).start();

В качестве альтернативы вы можете пропустить обработчик и напрямую использовать метод post в представлении:

new Thread(new Runnable(){
  @Override
  public void run () {
    mUiView.post(new Runnable() {
     @Override
     public void run () {
       mUiView.setX(x);
     }
    });
  }
}).start();

Это хороший пост, в котором описывается разница: Что именно делает метод post?

person worked    schedule 24.01.2014

используйте handler.post(), когда вы хотите опубликовать код (обычно из фонового потока) в основной поток. Ага, ПОСТ, так же, как и ты, отправь кому-нибудь письмо. С помощью обработчика код будет выполнен как можно быстрее, т.е. почти сразу.

person Community    schedule 27.03.2017