Od Androida 17 aplikacje kierowane na Androida 17 lub nowszego otrzymują nową implementację android.os.MessageQueue bez blokad. Nowa implementacja zwiększa wydajność i zmniejsza liczbę pominiętych klatek, ale może powodować awarie klientów, którzy korzystają z pól i metod prywatnych MessageQueue.
Android 17 wprowadza znaczące zmiany w sposobie działania Looper i Handler poprzez przepisanie klasy bazowej MessageQueue.
Od pierwszej wersji systemu operacyjnego Android MessageQueue polegał na jednej blokadzie do zarządzania kolejką zadań wątku głównego. Taka konstrukcja często powodowała spory o blokady. Wątek główny mógł być blokowany przez wątek w tle, co prowadziło do utraty klatek i zacinania się interfejsu.
Ograniczanie wpływu
Ta zmiana może mieć wpływ na Twoją aplikację, jeśli ona lub jej zależności korzystają z odzwierciedlenia w czasie działania, aby zajrzeć do MessageQueue. Unikaj używania odbicia w czasie działania do sprawdzania MessageQueue.
W przypadku starszej implementacji deweloperzy czasami uzyskiwali dostęp do pól prywatnych, takich jak MessageQueue.mMessages, aby sprawdzać oczekujące wiadomości. W nowej implementacji bez blokad wewnętrzne struktury danych uległy całkowitej zmianie.
Aby zachować zgodność binarną, w Androidzie 17 pole mMessages jest zachowane, ale w nowej implementacji to pole jest zawsze puste, niezależnie od tego, czy w kolejce znajdują się wiadomości.
Jeśli używasz popularnych bibliotek testowych, musisz też zaktualizować biblioteki, aby były zgodne z nową implementacją MessageQueue.
Espresso
Espresso jest często używane do testowania interfejsu. Biblioteka Espresso musi wiedzieć, kiedy wątek główny jest bezczynny, aby prawidłowo sprawdzać stan interfejsu. Wcześniejsze wersje Espresso korzystały z technik odbicia, które nie są już zgodne z kolejką MessageQueue bez blokad.
Działanie
Zaktualizuj do wersji Espresso 3.7.0 lub nowszej. Ta wersja korzysta z interfejsu TestLooperManager API, a zwłaszcza z nowych interfejsów API wprowadzonych w Androidzie 16, aby bezpiecznie wchodzić w interakcje z Looper bez polegania na szczegółach implementacji wewnętrznej.
Robolectric
Podobnie jeśli uruchamiasz testy jednostkowe za pomocą Robolectric, możesz napotkać problemy, jeśli Twoje testy opierają się na starszym trybie Looper.
Działanie
Zaktualizuj Robolectric do wersji 4.17 lub nowszej. Jeśli korzystasz z @LooperMode(LEGACY), musisz przenieść testy do nowej usługi @LooperMode(PAUSED). Więcej informacji znajdziesz w przewodniku po migracji Robolectric.
Testowanie zachowania
Możesz przetestować aplikację ze zmianą w działaniu na Androidzie 17 bez aktualizowania jejtargetSDK, wykonując to polecenie:
adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>
To polecenie włącza w aplikacji blokadę MessageQueue, jeśli jest to wersja z możliwością debugowania.
Jeśli Twoja aplikacja jest kierowana na Androida 17, nowe zachowanie jest domyślnie włączone. Jeśli po kierowaniu na ten poziom interfejsu API zauważysz nieoczekiwane działanie lub awarie, możesz tymczasowo wyłączyć nową implementację, aby sprawdzić, czy przyczyną jest MessageQueue.
Zmianę możesz włączyć lub wyłączyć na 2 sposoby:
Uruchom to polecenie ADB:
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
Spowoduje to przywrócenie w aplikacji starszej implementacji opartej na blokadach, co pozwoli Ci sprawdzić, czy problem wynikał ze zmiany w działaniu kolejki komunikatów.