Indicazioni per la modifica del comportamento di MessageQueue

A partire da Android 17, le app che hanno come target Android 17 (livello API 37) o versioni successive ricevono una nuova implementazione senza blocco di android.os.MessageQueue. La nuova implementazione migliora il rendimento e riduce i frame persi, ma potrebbe interrompere i client che riflettono sui campi e sui 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 basava su un singolo blocco per gestire la coda di attività del thread principale. Questo design spesso causava conflitti di blocco; il thread principale poteva essere bloccato da un thread in background, causando frame persi e jank dell'UI.

Ridurre l'impatto

La tua app potrebbe essere interessata da questa modifica se essa o le sue dipendenze si basano su reflection di runtime per esaminare MessageQueue. Evita di utilizzare la reflection di runtime per ispezionare MessageQueue.

Con l'implementazione legacy, gli sviluppatori a volte accedevano a campi privati come MessageQueue.mMessages per esaminare i messaggi in attesa. Con la nuova implementazione senza blocco, le strutture di dati interne sono cambiate completamente. Per mantenere la compatibilità binaria, Android 17 mantiene il campo mMessages, ma nell a nuova implementazione questo campo è sempre null, indipendentemente dal fatto che ci siano messaggi nella coda.

Inoltre, se utilizzi alcune librerie di test comuni, dovrai aggiornarle per renderle compatibili con la nuova implementazione di MessageQueue.

Espresso

Espresso viene comunemente utilizzato per i test dell'UI. La libreria Espresso deve sapere quando il thread principale è inattivo per asserire correttamente lo stato dell'UI. Le versioni precedenti di Espresso si basavano su tecniche di reflection che non sono più compatibili con MessageQueue senza blocco.

Azione

Esegui l'aggiornamento a Espresso 3.7.0 o versioni successive. Questa versione utilizza l' TestLooperManager API, in particolare le nuove API introdotte da Android 16, per interagire in sicurezza con Looper senza fare affidamento sui 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.

Verificare 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 blocco nella tua app, se si tratta di una build di cui è possibile eseguire il debug.

Se la tua app ha come target Android 17 (livello API 37), il nuovo comportamento è attivato per impostazione predefinita. Se noti comportamenti imprevisti o arresti anomali dopo aver impostato come target questo livello API, puoi disattivare temporaneamente la nuova implementazione per verificare se la causa è MessageQueue.

Puoi attivare o disattivare la modifica utilizzando una delle due opzioni seguenti:

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

  2. Eseguendo il seguente comando ADB:

    adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
    

In questo modo, l'app torna all'implementazione legacy basata su blocco, consentendoti di identificare se il problema è dovuto a una modifica del comportamento della coda dei messaggi.