Wskazówki dotyczące zmian w działaniu MessageQueue

Począwszy od Androida 17 aplikacje kierowane na Androida 17 (API na poziomie 37) lub nowszego otrzymują nową implementację android.os.MessageQueue bez blokady. Nowa implementacja zwiększa wydajność i zmniejsza liczbę pominiętych klatek, ale może powodować błędy u klientów, którzy korzystają z prywatnych pól i metod MessageQueue.

Android 17 wprowadza znaczące zmiany w działaniu Looper i Handler przez przepisanie klasy bazowej MessageQueue. Od pierwszej wersji systemu operacyjnego Android MessageQueue korzysta z jednej blokady do zarządzania kolejką zadań wątku głównego. Taki projekt często powodował rywalizację o blokadę – wątek główny mógł zostać zablokowany przez wątek w tle, co prowadziło do pomijania klatek i zacinania się interfejsu.

Zmniejszanie wpływu

Ta zmiana może mieć wpływ na Twoją aplikację, jeśli ona lub jej zależności korzystają z refleksji w czasie działania do sprawdzania MessageQueue. Unikaj używania refleksji w czasie działania do sprawdzania MessageQueue.

W starszej implementacji deweloperzy czasami uzyskiwali dostęp do pól prywatnych, takich jak MessageQueue.mMessages, aby sprawdzać oczekujące wiadomości. Dzięki nowej implementacji bez blokad wewnętrzne struktury danych uległy całkowitej zmianie. Aby zachować zgodność plików binarnych, Android 17 zachowuje pole mMessages, ale w nowej implementacji to pole zawsze ma wartość null, niezależnie od tego, czy w kolejce są wiadomości.

Jeśli używasz niektórych popularnych bibliotek testowych, musisz je zaktualizować, aby były zgodne z nową implementacją MessageQueue.

Espresso

Espresso jest powszechnie używane do testowania interfejsu. Biblioteka Espresso musi wiedzieć, kiedy wątek główny jest bezczynny, aby prawidłowo określić stan interfejsu. Wcześniejsze wersje Espresso korzystały z technik refleksji, które nie są już zgodne z bezblokadową kolejką MessageQueue.

Działanie

Zaktualizuj do wersji Espresso 3.7.0 lub nowszej. Ta wersja używa interfejsu API TestLooperManager, a w szczególności nowych interfejsów API wprowadzonych w Androidzie 16, aby bezpiecznie wchodzić w interakcje z Looper bez polegania na wewnętrznych szczegółach implementacji.

Robolectric

Podobnie, jeśli przeprowadzasz testy jednostkowe za pomocą Robolectric, możesz napotkać problemy, jeśli testy opierają się na starszym trybie Looper.

Działanie

Zaktualizuj do wersji Robolectric 4.17 lub nowszej. Jeśli używasz @LooperMode(LEGACY), musisz przenieść testy do nowej wersji @LooperMode(PAUSED). Więcej informacji znajdziesz w przewodniku po migracji Robolectric.

Testowanie działania

Możesz przetestować aplikację ze zmianą działania na Androidzie 17 bez aktualizowania targetSDK, wykonując to polecenie:

adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>

To polecenie włącza w aplikacji bezblokadową funkcję MessageQueue, jeśli jest to kompilacja z możliwością debugowania.

Jeśli aplikacja jest kierowana na Androida 17 (API na poziomie 37), nowe działanie jest domyślnie włączone. Jeśli po ustawieniu tego poziomu interfejsu API zauważysz nieoczekiwane działanie lub awarie, możesz tymczasowo wyłączyć nową implementację, aby sprawdzić, czy przyczyną jest MessageQueue.

Możesz przełączać się między tymi opcjami na 2 sposoby:

  1. Menu Zmiany dotyczące zgodności aplikacji w Opcjach programisty.

  2. Uruchamiając to polecenie ADB:

    adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
    

Spowoduje to przywrócenie starszej implementacji opartej na blokadzie, co pozwoli Ci sprawdzić, czy problem był spowodowany zmianą działania kolejki wiadomości.