← Назад к вопросам

В какой структуре данных Looper сохраняет полученные от Handler сообщения

2.2 Middle🔥 122 комментариев
#Android компоненты#Коллекции и структуры данных#Многопоточность и асинхронность

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Структура хранения сообщений в Looper

Основная структура данных, которую Looper использует для хранения сообщений от Handler, — это MessageQueue (очередь сообщений). Однако важно понимать внутреннюю реализацию этой очереди.

Внутренняя реализация MessageQueue

MessageQueue в Android не использует стандартные коллекции Java вроде LinkedList или PriorityQueue. Вместо этого она реализована как односвязный список (singly linked list) объектов Message, организованный в виде приоритетной очереди.

Ключевые особенности структуры:

1. Структура Message

Каждое сообщение (Message) содержит поля для формирования связного списка:

// Упрощенная структура Message
public final class Message {
    public int what;           // Идентификатор сообщения
    public Object obj;         // Данные сообщения
    public long when;          // Время выполнения
    Message next;              // Ссылка на следующее сообщение
    static Message sPool;      // Пул для переиспользования
}

2. Принцип работы MessageQueue

  • Организация по времени: Сообщения хранятся в порядке времени их выполнения (поле when), формируя приоритетную очередь
  • Односвязный список: Каждое сообщение содержит ссылку next на следующее сообщение
  • Минимизация аллокаций: Используется пул сообщений для переиспользования объектов

Пример работы со списком сообщений

// Псевдокод демонстрации добавления сообщения
public boolean enqueueMessage(Message msg, long when) {
    synchronized (this) {
        msg.when = when;
        Message p = mMessages; // Голова списка
        
        // Вставка в нужную позицию согласно времени выполнения
        if (p == null || when == 0 || when < p.when) {
            // Вставка в начало
            msg.next = p;
            mMessages = msg;
        } else {
            // Поиск правильной позиции в середине/конце списка
            Message prev;
            do {
                prev = p;
                p = p.next;
            } while (p != null && when >= p.when);
            
            msg.next = p;
            prev.next = msg;
        }
        
        // Пробуждение Looper, если нужно
        if (needWake) {
            nativeWake(mPtr);
        }
    }
    return true;
}

Ключевые аспекты реализации

Сортировка по времени

  • Сообщения с when = 0 (немедленное выполнение) вставляются в начало
  • Сообщения с задержкой вставляются в соответствии со временем их выполнения
  • Повторяющиеся сообщения (postDelayed) автоматически переупорядочиваются

Пул сообщений

// Пример использования пула
Message obtainMessage() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;  // Берем из головы списка пула
            m.next = null;
            return m;
        }
    }
    return new Message();
}

Native Component

Важная деталь: MessageQueue содержит нативный компонент (Native Looper), который:

  • Использует epoll на Linux для эффективного ожидания
  • Обрабатывает файловые дескрипторы (включая UI события)
  • Позволяет "засыпать", когда нет сообщений, экономя заряд батареи

Преимущества выбранной реализации

  • Эффективность по памяти: Связный список использует только дополнительный указатель next
  • Быстрое добавление: O(1) для вставки в начало, O(n) для середины (при небольшом n - эффективно)
  • Пул объектов: Избегает частой сборки мусора для короткоживущих сообщений
  • Гибкость: Легко поддерживает отмену сообщений (removeMessages())

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

Looper непрерывно извлекает сообщения из этой очереди через метод loop(), который в цикле вызывает queue.next() для получения следующего сообщения для обработки соответствующему Handler.

В какой структуре данных Looper сохраняет полученные от Handler сообщения | PrepBro