В чем разница между этими методами запуска кода в потоке пользовательского интерфейса?

В Интернете опубликованы различные методы запуска кода в потоке пользовательского интерфейса. Все они выполняют одну и ту же задачу, однако я действительно хочу знать разницу между этими методами.

Способ 1:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

Метод 2:

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

Способ 3:

 runOnUiThread(new Runnable() {
     @Override
     public void run() {
     // Code here will run in UI thread
     }
 });

person Mena    schedule 01.10.2019    source источник
comment
stackoverflow.com/questions/13974661 /   -  person IntelliJ Amiya    schedule 01.10.2019


Ответы (3)


В Android поток может иметь один Looper или MessageQueue. Обработчик используется для отправки Message или публикации Runnable в MessageQueue потока, и он всегда должен быть связан с Looper или MessageQueue потока.

Способ 1

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

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

Приведенный выше код создает обработчик и связан с Looper потока пользовательского интерфейса, поэтому исполняемый объект будет поставлен в очередь в MessageQueue потока пользовательского интерфейса и будет выполнен позже.

Метод 2

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

Создание обработчика и связывание с Looper текущего потока возможно в 3 случаях:

  • Если этот код выполняется в потоке пользовательского интерфейса, то исполняемый объект будет поставлен в очередь в MessageQueue потока пользовательского интерфейса и будет выполнен позже.
  • Если этот код выполняется в фоновом потоке, если в этом потоке есть Looper, тогда исполняемый объект будет помещен в очередь MessageQueue фонового потока и будет выполнен позже.
  • Если этот код выполняется в фоновом потоке и в этом потоке нет Looper, то будет выдано исключение.

Способ 3

runOnUiThread(new Runnable() {
     @Override
     public void run() {
     // Code here will run in UI thread
     }
});

runOnUiThread – это просто служебный метод Активность используется, когда вы хотите выполнить некоторый код в потоке пользовательского интерфейса. Логика этого метода заключается в том, что если текущий поток является потоком пользовательского интерфейса, то он выполняется немедленно, в противном случае используется обработчик для отправки сообщения в MessageQueue потока пользовательского интерфейса (например, метод 1).

person Son Truong    schedule 02.10.2019
comment
Идеальное подробное объяснение! - person Mena; 02.10.2019

Метод 1 всегда будет работать.

Метод 2 будет работать только в том случае, если вы уже находитесь в потоке пользовательского интерфейса — новый обработчик без параметра Looper создает обработчик для текущего потока (и терпит неудачу, если в текущем потоке нет Looper).

Метод 3 должен выполняться в действии или вызываться в объекте действия, поскольку runOnUiThread — это функция действия. Но под капотом он будет делать то же самое, что и 1 (хотя, вероятно, держит один обработчик, чтобы быть более эффективным, а не постоянно обновлять его).

person Gabe Sechan    schedule 01.10.2019

Все методы работают так:

Обработчик цикла Метод 1, если цикл существует

Обработчик метода 2 может работать во всех действиях, если они не являются частными или желательными.

Обработчик метода 3 может работать только в текущей активности

person Nina    schedule 01.10.2019