A partire da Android 17, le app che hanno come target Android 17
o versioni successive ricevono una nuova implementazione senza blocchi di
android.os.MessageQueue. La nuova implementazione migliora il rendimento e
riduce i frame mancanti, ma potrebbe interrompere i client che riflettono su campi e metodi privati di MessageQueue.
Android 17 introduce una revisione significativa del funzionamento di Looper e
Handler, riscrivendo la classe MessageQueue sottostante.
Dalla prima release del sistema operativo Android, MessageQueue si basa
su un unico blocco per gestire la coda di attività del thread principale. Questo design spesso
causava contese di blocco; il thread principale poteva essere bloccato da un thread in background,
con conseguente perdita di frame e jank dell'interfaccia utente.
Mitigare l'impatto
La tua app potrebbe essere interessata da questa modifica se essa o le sue dipendenze si basano sulla
reflection in fase di runtime per esaminare MessageQueue. Evita di utilizzare la reflection
in fase di runtime per esaminare MessageQueue.
Con l'implementazione precedente, a volte gli sviluppatori accedevano a campi privati
come MessageQueue.mMessages per esaminare i messaggi in attesa. Con la nuova implementazione senza blocchi, le strutture di dati interne sono cambiate completamente.
Per mantenere la compatibilità binaria, Android 17 mantiene il campo mMessages, ma nella
nuova implementazione questo campo è sempre nullo, indipendentemente dal fatto che
ci siano messaggi nella coda.
Inoltre, se utilizzi alcune librerie di test popolari, dovrai aggiornarle
per renderle compatibili con la nuova implementazione di MessageQueue.
Espresso
Espresso viene comunemente utilizzato per il test della UI. La libreria Espresso deve sapere quando il thread principale è inattivo per verificare correttamente lo stato dell'interfaccia utente. Le versioni precedenti di Espresso si basavano su tecniche di reflection non più compatibili con MessageQueue senza blocchi.
Azione
Esegui l'aggiornamento a Espresso 3.7.0 o versioni successive. Questa versione utilizza l'API
TestLooperManager, in particolare le nuove API introdotte da Android 16,
per interagire in modo sicuro con Looper senza fare affidamento su dettagli di implementazione
interni.
Robolectric
Allo stesso modo, se esegui test delle unità utilizzando Robolectric, potresti riscontrare problemi se i test si basano sulla modalità Looper legacy.
Azione
Esegui l'aggiornamento a Robolectric 4.17 o versioni successive. Se utilizzi @LooperMode(LEGACY),
dovrai eseguire la migrazione dei test al nuovo @LooperMode(PAUSED). Per ulteriori informazioni, consulta la
guida alla migrazione di Robolectric.
Testa il comportamento
Puoi testare la tua app con la modifica del comportamento su Android 17 senza aggiornare
targetSDK eseguendo il seguente comando:
adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>
Questo comando attiva MessageQueue senza blocchi nell'app, se si tratta di una
build sottoponibile a debug.
Se la tua app ha come target Android 17, il nuovo comportamento è attivato
per impostazione predefinita. Se noti comportamenti imprevisti o arresti anomali dopo aver scelto come target questo
livello API, puoi disattivare temporaneamente la nuova implementazione per verificare se
MessageQueue è la causa.
Puoi attivare/disattivare la modifica utilizzando una delle due opzioni:
Il menu Modifiche alla compatibilità delle app in Opzioni sviluppatore.
Eseguendo questo comando ADB:
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
In questo modo, l'app viene ripristinata all'implementazione legacy basata sul blocco, consentendoti di identificare se il problema è il risultato di una modifica del comportamento della coda di messaggi.