Ab Android 17 erhalten Apps, die auf Android 17 (API-Level 37)
oder höher ausgerichtet sind, eine neue sperrenfreie Implementierung von
android.os.MessageQueue. Die neue Implementierung verbessert die Leistung und reduziert fehlende Frames, kann aber bei Clients zu Problemen führen, die private Felder und Methoden von MessageQueue verwenden.
Mit Android 17 wird die Funktionsweise von Looper und
Handler grundlegend überarbeitet, indem die zugrunde liegende MessageQueue-Klasse neu geschrieben wird.
Seit der ersten Version des Android-Betriebssystems verwendet MessageQueue eine einzelne Sperre, um die Aufgabenwarteschlange des Hauptthreads zu verwalten. Dieses Design führte oft zu Sperrenkonflikten. Der Hauptthread konnte durch einen Hintergrundthread blockiert werden, was zu fehlenden Frames und UI-Rucklern führte.
Auswirkungen minimieren
Diese Änderung kann sich auf Ihre App auswirken, wenn sie oder ihre Abhängigkeiten sich auf
Laufzeitreflexion verlassen, um in MessageQueue zu suchen. Verwenden Sie die Laufzeitreflexion nicht, um MessageQueue zu prüfen.
Bei der Legacy-Implementierung haben Entwickler manchmal auf private Felder wie MessageQueue.mMessages zugegriffen, um ausstehende Nachrichten zu prüfen. Bei der neuen sperrenfreien Implementierung haben sich die internen Datenstrukturen vollständig geändert.
Um die binäre Kompatibilität beizubehalten, behält Android 17 das mMessages Feld bei. In
der neuen Implementierung ist dieses Feld jedoch immer null, unabhängig davon, ob
sich Nachrichten in der Warteschlange befinden.
Wenn Sie außerdem einige beliebte Testbibliotheken verwenden, müssen Sie Ihre Bibliotheken aktualisieren, damit sie mit der neuen MessageQueue-Implementierung kompatibel sind.
Espresso
Espresso wird häufig für UI-Tests verwendet. Die Espresso-Bibliothek muss wissen, wann der Hauptthread im Leerlauf ist, um den UI-Status korrekt zu bestätigen. Frühere Versionen von Espresso verwendeten Reflexionstechniken, die nicht mehr mit der sperrenfreien MessageQueue kompatibel sind.
Aktion
Aktualisieren Sie auf Espresso 3.7.0 oder höher. Diese Version verwendet die
TestLooperManager API, insbesondere neue APIs, die mit Android 16 eingeführt wurden,
um sicher mit dem Looper zu interagieren, ohne auf interne Implementierungs
details angewiesen zu sein.
Robolectric
Wenn Sie Einheitentests mit Robolectric ausführen, können ebenfalls Probleme auftreten, wenn Ihre Tests auf dem Legacy-Looper-Modus basieren.
Aktion
Aktualisieren Sie auf Robolectric 4.17 oder höher. Wenn Sie @LooperMode(LEGACY) verwenden, müssen Sie Ihre Tests zu @LooperMode(PAUSED) migrieren. Weitere Informationen finden Sie im
Migrationsleitfaden von Robolectric.
Verhalten testen
Sie können Ihre App mit der Verhaltensänderung unter Android 17 testen, ohne targetSDK zu aktualisieren. Führen Sie dazu den folgenden Befehl aus:
adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>
Mit diesem Befehl wird die sperrenfreie MessageQueue in Ihrer App aktiviert, wenn es sich um einen debugfähigen Build handelt.
Wenn Ihre App auf Android 17 (API-Level 37) ausgerichtet ist, ist das neue Verhalten standardmäßig aktiviert. Wenn nach der Ausrichtung auf dieses API-Level unerwartetes Verhalten oder Abstürze auftreten, können Sie die neue Implementierung vorübergehend deaktivieren, um zu prüfen, ob MessageQueue die Ursache ist.
Sie haben zwei Möglichkeiten, die Änderung zu aktivieren oder zu deaktivieren:
Das Menü Änderungen bei der App-Kompatibilität in den Entwickleroptionen.
Führen Sie den folgenden ADB-Befehl aus:
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
Dadurch wird Ihre App auf die Legacy-Implementierung mit Sperren zurückgesetzt. So können Sie feststellen, ob das Problem auf eine Änderung des Verhaltens der Nachrichtenwarteschlange zurückzuführen ist.