À partir d'Android 17, les applications ciblant Android 17 (niveau d'API 37)
ou une version ultérieure reçoivent une nouvelle implémentation sans verrouillage de
android.os.MessageQueue. La nouvelle implémentation améliore les performances et réduit le nombre d'images manquées, mais peut endommager les clients qui reflètent les champs et méthodes privés MessageQueue.
Android 17 introduit une refonte significative du fonctionnement de Looper et
Handler, en réécrivant la classe MessageQueue sous-jacente.
Depuis la première version du système d'exploitation Android, MessageQueue s'appuie sur un seul verrou pour gérer la file d'attente des tâches du thread principal. Cette conception entraînait souvent une contention de verrouillage. Le thread principal pouvait être bloqué par un thread en arrière-plan, ce qui entraînait une perte d'images et des à-coups de l'UI.
Limiter l'impact
Votre application peut être affectée par cette modification si elle ou ses dépendances s'appuient sur
la réflexion d'exécution pour examiner MessageQueue. Évitez d'utiliser la réflexion d'exécution pour inspecter MessageQueue.
Avec l'implémentation héritée, les développeurs accédaient parfois à des champs privés tels que MessageQueue.mMessages pour inspecter les messages en attente. Avec la nouvelle implémentation sans verrouillage, les structures de données internes ont complètement changé.
Pour maintenir la compatibilité binaire, Android 17 conserve le champ mMessages, mais dans
la nouvelle implémentation, ce champ est toujours nul, qu'il y ait ou non des messages dans la file d'attente.
De plus, si vous utilisez des bibliothèques de test populaires, vous devrez les mettre à jour pour qu'elles soient compatibles avec la nouvelle implémentation MessageQueue.
Espresso
Espresso est couramment utilisé pour les tests d'UI. La bibliothèque Espresso doit savoir quand le thread principal est inactif pour affirmer correctement l'état de l'UI. Les versions antérieures d'Espresso s'appuyaient sur des techniques de réflexion qui ne sont plus compatibles avec MessageQueue sans verrouillage.
Action
Passez à Espresso 3.7.0 ou version ultérieure. Cette version utilise l'
TestLooperManager API, en particulier les nouvelles API introduites par Android 16,
pour interagir en toute sécurité avec le Looper sans s'appuyer sur les détails d'implémentation
internes.
Robolectric
De même, si vous exécutez des tests unitaires à l'aide de Robolectric, vous pouvez rencontrer des problèmes si vos tests s'appuient sur l'ancien mode Looper.
Action
Passez à Robolectric 4.17 ou version ultérieure. Si vous utilisez @LooperMode(LEGACY), vous devrez migrer vos tests vers le nouveau @LooperMode(PAUSED). Pour en savoir plus, consultez le
guide de migration de Robolectric.
Tester le comportement
Vous pouvez tester votre application avec le changement de comportement sur Android 17 sans mettre à jour targetSDK en exécutant la commande suivante :
adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>
Cette commande active MessageQueue sans verrouillage dans votre application, s'il s'agit d'une version débogable.
Si votre application cible Android 17 (niveau d'API 37), le nouveau comportement est activé par défaut. Si vous constatez un comportement inattendu ou des plantages après avoir ciblé ce niveau d'API, vous pouvez désactiver temporairement la nouvelle implémentation pour vérifier si MessageQueue est la cause du problème.
Vous pouvez activer ou désactiver la modification à l'aide de l'une des deux options suivantes :
Le menu Modifications de la compatibilité de l'application dans Options pour les développeurs.
En exécutant la commande ADB suivante :
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
Cette opération rétablit l'implémentation héritée basée sur le verrouillage de votre application, ce qui vous permet de déterminer si le problème est dû à une modification du comportement de la file d'attente des messages.