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

Как Looper связывается с потоком

2.0 Middle🔥 142 комментариев
#Android компоненты#Многопоточность и асинхронность

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

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

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

Как Looper связывается с потоком в Android

Looper — это механизм, который превращает обычный поток в поток с циклом обработки сообщений (Message Queue). Он позволяет потоку выполнять задачи асинхронно, обрабатывая сообщения и Runnable-задачи в порядке очереди. Связь Looper с потоком обеспечивается через ThreadLocal — хранилище данных, уникальное для каждого потока.

Ключевые шаги связывания

  1. Подготовка Looper в потоке
    Перед использованием Looper его необходимо инициализировать в потоке вызовом Looper.prepare(). Этот метод создает экземпляр Looper и сохраняет его в ThreadLocal для текущего потока.

    class WorkerThread extends Thread {
        public Handler handler;
        
        @Override
        public void run() {
            // Инициализация Looper для текущего потока
            Looper.prepare();
            
            // Создание Handler, привязанного к Looper этого потока
            handler = new Handler();
            
            // Запуск бесконечного цикла обработки сообщений
            Looper.loop();
        }
    }
    
  2. Хранение в ThreadLocal
    Внутри класса Looper находится статическое поле sThreadLocal типа ThreadLocal<Looper>. При вызове prepare() созданный Looper помещается в это хранилище:

    // Упрощенная реализация из исходного кода Android
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
    
    public static void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }
    
  3. Получение Looper потока
    Метод Looper.myLooper() возвращает экземпляр Looper, связанный с текущим потоком, путем выборки из ThreadLocal:

    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
    
  4. Основной цикл обработки (Looping)
    После подготовки вызывается Looper.loop(), который запускает бесконечный цикл. В этом цикле из MessageQueue извлекаются сообщения и передаются в соответствующие Handler для выполнения:

    public static void loop() {
        final Looper me = myLooper(); // Получение Looper текущего потока
        final MessageQueue queue = me.mQueue; // Получение очереди сообщений
        
        for (;;) {
            Message msg = queue.next(); // Блокируется, если сообщений нет
            if (msg == null) return; // Выход при отсутствии Looper
            msg.target.dispatchMessage(msg); // Передача сообщения в Handler
        }
    }
    

Особенности связывания

  • Главный поток (UI Thread) уже имеет предустановленный Looper, который создается системой при запуске приложения. Его можно получить через Looper.getMainLooper().
  • Один Looper на поток — попытка создать второй Looper в том же потоке вызовет исключение RuntimeException.
  • Завершение работы — чтобы остановить цикл, нужно вызвать Looper.quit() или Looper.quitSafely(), что приведет к выходу из loop().

Пример полного жизненного цикла

// Создание кастомного потока с Looper
Thread backgroundThread = new Thread(() -> {
    Looper.prepare(); // 1. Привязка Looper к потоку
    Handler handler = new Handler(); // 2. Handler автоматически использует Looper текущего потока
    Looper.loop(); // 3. Запуск цикла (поток теперь обрабатывает сообщения)
});
backgroundThread.start();

// Отправка задачи в кастомный поток
handler.post(() -> {
    // Этот код выполнится в backgroundThread
    Log.d("LooperExample", "Task executed in background thread");
});

Заключение

Таким образом, связь между Looper и потоком обеспечивается через ThreadLocal, что гарантирует изоляцию экземпляра Looper для каждого потока. Это основа архитектуры обработки сообщений в Android, позволяющая организовать асинхронное выполнение задач с сохранением потокобезопасности. Looper является критическим компонентом для Handler, HandlerThread и всей системы сообщений Android.

Как Looper связывается с потоком | PrepBro