Sobes.tech
Junior

Czym jest Looper w Androidzie?

sobes.tech AI

Odpowiedź od AI

Looper to klasa w Android, która służy do zarządzania przepływem (wątkiem), czyniąc go "Looping" (cyklicznym). Przygotowuje wątek do obsługi wiadomości z kolejki wiadomości (MessageQueue) do momentu jego jawnego zakończenia.

Główne komponenty Looper:

  • MessageQueue: Kolejka przechowująca wiadomości (Message) i zadania (Runnable) do wykonania w wątku Looper. Jest to struktura bezpieczna dla wątków.
  • Looper: Łączy wątek z MessageQueue i cyklicznie wyciąga wiadomości z kolejki do dalszej obsługi.
  • Handler: Obiekt, który umieszcza wiadomości i zadania w MessageQueue Looper i obsługuje je po wyciągnięciu z kolejki. Handler jest powiązany z określonym Looperem.

Jak działa Looper:

  1. Przygotowanie: W wątku wywołuje się Looper.prepare(). Tworzy to nową instancję Looper i łączy ją z bieżącym wątkiem. Tworzona jest również MessageQueue dla tego Loopera.
  2. Rozpoczęcie pętli: Wywołuje się Looper.loop(). Ta metoda wchodzi w nieskończoną pętlę (dopóki Looper nie zostanie zakończony). W pętli Looper stale sprawdza MessageQueue pod kątem nowych wiadomości.
  3. Obsługa wiadomości: Znalezienie wiadomości powoduje, że Looper ją wyciąga i wysyła do Handlera, który ją dodał do kolejki. Handler wykonuje odpowiednie zadanie (np. wywołanie handleMessage() lub run() dla Runnable).
  4. Zakończenie: Aby wyjść z pętli i zakończyć Looper, należy wywołać Looper.quit() lub Looper.quitSafely().

Typowe zastosowania Looper:

  • Tworzenie wątków tła, które mają wykonywać zadania asynchroniczne i odbierać wiadomości z wątku UI lub innych wątków.
  • Użycie w serwisach (IntentService korzysta z wbudowanego Loopera).
  • Praca z HandlerThread (specjalna klasa wątku tworząca własny Looper i MessageQueue).

Przykład tworzenia wątku z Looperem i Handlerem:

// Tworzymy i uruchamiamy wątek
HandlerThread handlerThread = new HandlerThread("MyWorkerThread");
handlerThread.start();

// Pobieramy Looper z wątku
Looper looper = handlerThread.getLooper();

// Tworzymy Handler powiązany z Looperem
Handler handler = new Handler(looper) {
    @Override
    public void handleMessage(Message msg) {
        // Obsługa wiadomości w wątku roboczym
        // msg.what zawiera identyfikator wiadomości
        // msg.obj lub msg.data mogą zawierać dane
        switch (msg.what) {
            case 1:
                // Obsługa wiadomości typu 1
                break;
            case 2:
                // Obsługa wiadomości typu 2
                break;
        }
    }
};

// Wysyłanie wiadomości do wątku roboczego
handler.sendEmptyMessage(1);

// Lub uruchomienie Runnable
handler.post(new Runnable() {
    @Override
    public void run() {
        // Kod wykonywany w wątku roboczym
    }
});

// Gdy wątek nie jest już potrzebny, kończymy Looper i wątek
handlerThread.quitSafely();