Od Androida 17 aplikacje kierowane na Androida 17 (API na poziomie 37)
lub nowszego otrzymują nową implementację bez blokad
android.os.MessageQueue. Nowa implementacja zwiększa wydajność i zmniejsza liczbę pominiętych klatek, ale może spowodować problemy u klientów, którzy korzystają z prywatnych pól i metod MessageQueue.
Android 17 wprowadza znaczące zmiany w sposobie działania Looper i
Handler przez przepisanie podstawowej klasy MessageQueue.
Od pierwszej wersji systemu operacyjnego Android MessageQueue korzysta z jednej blokady do zarządzania kolejką zadań wątku głównego. Taka konstrukcja często powodowała konflikty blokad. Wątek główny mógł być blokowany przez wątek działający w tle, co prowadziło do pomijania 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
odbicia w czasie działania, aby zajrzeć do MessageQueue. Unikaj używania odbicia w czasie działania do sprawdzania MessageQueue.
W starszej implementacji programiści czasami uzyskiwali dostęp do prywatnych pól, takich jak MessageQueue.mMessages, aby sprawdzić oczekujące wiadomości. W nowej implementacji bez blokad wewnętrzne struktury danych zostały całkowicie zmienione.
Aby zachować zgodność binarną, Android 17 zachowuje pole mMessages, ale w
nowej implementacji to pole jest zawsze wartością null, niezależnie od tego, czy
w kolejce znajdują się wiadomości.
Jeśli używasz 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 sprawdzać stan interfejsu. Wcześniejsze wersje Espresso korzystały z technik odbicia, które nie są już zgodne z MessageQueue bez blokad.
Działanie
Zaktualizuj bibliotekę do Espresso 3.7.0 lub nowszej. Ta wersja korzysta z
TestLooperManager interfejsu API, w szczególności z 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 uruchamiasz testy jednostkowe za pomocą Robolectric, możesz napotkać problemy, jeśli Twoje testy korzystają ze starszego trybu Looper.
Działanie
Zaktualizuj bibliotekę do Robolectric 4.17 lub nowszej. Jeśli używasz @LooperMode(LEGACY), musisz przenieść testy do nowego @LooperMode(PAUSED). Więcej informacji znajdziesz w
przewodniku po migracji Robolectric.
Testowanie zachowania
Możesz przetestować swoją aplikację pod kątem zmiany zachowania w 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 MessageQueue bez blokad, jeśli jest to kompilacja z możliwością debugowania.
Jeśli Twoja aplikacja jest kierowana na Androida 17 (API na poziomie 37), nowe zachowanie jest domyślnie włączone. Jeśli po kierowaniu na ten poziom interfejsu API zauważysz nieoczekiwane zachowanie lub awarie, możesz tymczasowo wyłączyć nową implementację, aby sprawdzić, czy przyczyną jest MessageQueue.
Zmianę możesz przełączać na 2 sposoby:
W menu Opcje programisty wybierz Zmiany w zgodności aplikacji.
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 jest spowodowany zmianą zachowania kolejki wiadomości.