Indicazioni per la modifica del comportamento di MessageQueue

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:

  1. Il menu Modifiche alla compatibilità delle app in Opzioni sviluppatore.

  2. 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.