В этом уроке:

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

 

В прошлых уроках мы отправляли сообщения в очередь, а система сразу же доставала их и перенаправляла в Handler на обработку. Но мы можем настроить сообщение так, чтобы система отправило его на обработку не сразу, а с задержкой. Для этого используются методы sendEmptyMessageDelayed (если используете только what) и sendMessageDelayed (полное сообщение). В них мы можем указать паузу в миллисекундах. Система выждет эту паузу и только потом отправит сообщение в Handler.

Если вдруг поместили такое отложенное сообщение в очередь, а потом решили, что оно не должно уйти на обработку, то его можно из очереди удалить. Для этого используется метод removeMessages.

В прошлых уроках мы создавали свой Handler, и в его методе handleMessage кодили свой алгоритм обработки сообщений. Кроме этого способа Handler также может использовать для обработки сообщений объект, реализующий интерфейс Handler.Callback. У интерфейса всего один метод handleMessage – в нем и прописываем всю логику обработки сообщений. Я пока не встречал практической пользы от этой штуки, но все же разберемся, как ее можно использовать. Может когда и пригодится.

 

Создадим проект:

Project name: P0831_HandlerMessageManage
Build Target: Android 2.3.3
Application name: HandlerMessageManage
Package name: ru.startandroid.develop.p0831handlermessagemanage
Create Activity: MainActivity

 

strings.xml и main.xml не трогаем, они нам не нужны. Будем работать с логами. 

 

Кодим MainActivity.java:

package ru.startandroid.develop.p0831handlermessagemanage;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class MainActivity extends Activity {

  final String LOG_TAG = "myLogs";

  Handler h;

  Handler.Callback hc = new Handler.Callback() {
    public boolean handleMessage(Message msg) {
      Log.d(LOG_TAG, "what = " + msg.what);
      return false;
    }
  };

  /** Called when the activity is first created. */
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    h = new Handler(hc);
    sendMessages();
  }

  void sendMessages() {
    Log.d(LOG_TAG, "send messages");
    h.sendEmptyMessageDelayed(1, 1000);
    h.sendEmptyMessageDelayed(2, 2000);
    h.sendEmptyMessageDelayed(3, 3000);
  }
}

Мы создаем объект hc типа Handler.Callback. У него есть метод handleMessage, в котором мы будем обрабатывать сообщения. В нашем случае просто читаем атрибут what и выводим значение в лог.

В onCreate создаем handler, используя конструктор Handler (Handler.Callback callback). На вход передаем созданный ранее hc. И теперь Handler будет обрабатывать сообщения не сам, а перепоручит это объекту hc. Далее мы выполняем метод sendMessages , который кладет три сообщения в очередь сообщений. Для этого используется метод sendEmptyMessageDelayed. Это аналог знакомого нам метода sendEmptyMessage с прошлого урока. Он тоже заполняет в сообщении только атрибут what, но при этом он позволяет указать задержку в обработке сообщения. Т.е. сообщение будет извлечено из очереди и отправлено на обработку через указанное количество миллисекунд.

Итак, мы помещаем три сообщения:

1) what = 1, обработка через 1000 мс.
2) what = 2, обработка через 2000 мс.
3) what = 3, обработка через 3000 мс.

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

Все сохраним и запустим приложение. В логе одна за другой будут появляться записи:

10:21:07.759: D/myLogs(332): send messages
10:21:08.786: D/myLogs(332): what = 1
10:21:09.765: D/myLogs(332): what = 2
10:21:10.776: D/myLogs(332): what = 3

Обратите внимание на время этих записей. Первое срабатывает через 1000 мс после помещения в очередь (send messages), второе - через две секунды, третье – через три.

 

Теперь попробуем удалить  сообщение из очереди. Перепишем метод sendMessages:

  void sendMessages() {
    h.sendEmptyMessageDelayed(1, 1000);
    h.sendEmptyMessageDelayed(2, 2000);
    h.sendEmptyMessageDelayed(3, 3000);
    h.removeMessages(2);
  }

Используем метод removeMessages, в котором указываем значение атрибута what. Этот метод находит в очереди сообщение с атрибутом what, равным 2, и удаляет его из очереди.

Все сохраняем, запускаем приложение. Смотрим лог:

10:24:49.916: D/myLogs(434): send messages
10:24:50.927: D/myLogs(434): what = 1
10:24:52.948: D/myLogs(434): what = 3

Как видим, сообщение с what = 2 не сработало.

 

А если будет несколько сообщений с одинаковым значением what? Система удалит первое попавшееся или все?

Проверим. Перепишем sendMessages:

  void sendMessages() {
    Log.d(LOG_TAG, "send messages");
    h.sendEmptyMessageDelayed(1, 1000);
    h.sendEmptyMessageDelayed(2, 2000);
    h.sendEmptyMessageDelayed(3, 3000);
    h.sendEmptyMessageDelayed(2, 4000);
    h.sendEmptyMessageDelayed(5, 5000);
    h.sendEmptyMessageDelayed(2, 6000);
    h.sendEmptyMessageDelayed(7, 7000);
    h.removeMessages(2);
  }

Будем помещать в очередь кучу сообщений. Из них несколько с what = 2. Проверим, какие удалит система.

Запускаем приложение и смотрим лог:

10:29:23.297: D/myLogs(467): send messages
10:29:24.372: D/myLogs(467): what = 1
10:29:26.307: D/myLogs(467): what = 3
10:29:28.364: D/myLogs(467): what = 5
10:29:30.332: D/myLogs(467): what = 7

Все сообщения с what = 2 были удалены. Не забывайте это. А то захотите удалить одно последнее сообщение, а система найдет все подходящие, ожидающие обработки, и снесет их.

 

У метода removeMessages есть еще реализация с использованием obj. Тут все так же, только система ищет для удаления из очереди сообщения с указанными атрибутами what и obj.

Если хотите запланировать полноценное сообщение, а не просто what, то используйте метод sendMessageDelayed – на вход даете сообщение и указываете задержку обработки.

Есть еще методы sendEmptyMessageAtTime и sendMessageAtTime. Они тоже позволяют указать задержку обработки. Но эта задержка будет отсчитана от времени последнего старта системы, а не от времени помещения в очередь. Если сообщение окажется просроченным на момент помещения в очередь, оно выполняется сразу.

 

 

На следующем уроке:

- работаем с Handler и Runnable


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня




Language

Автор сайта

Дмитрий Виноградов

Подробнее можно посмотреть или почитать.

Никакие другие люди не имеют к этому сайту никакого отношения и просто занимаются плагиатом.

Социальные сети

 

В канале я публикую ссылки на интересные и полезные статьи по Android

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



Группа ВКонтакте



Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal