A partir do Android 17, os apps destinados ao Android 17
ou versões mais recentes recebem uma nova implementação sem bloqueio de
android.os.MessageQueue. A nova implementação melhora a performance e reduz os frames perdidos, mas pode causar falhas em clientes que refletem em campos e métodos particulares de MessageQueue.
O Android 17 introduz uma revisão significativa de como Looper e
Handler funcionam, reescrevendo a classe MessageQueue subjacente.
Desde o primeiro lançamento do sistema operacional Android, o MessageQueue dependia
de um único bloqueio para gerenciar a fila de tarefas da linha de execução principal. Esse design geralmente causava disputa de bloqueio. A linha de execução principal podia ser bloqueada por uma linha de execução em segundo plano, o que levava a perda de frames e instabilidade na interface.
Reduzir o impacto
Seu app pode ser afetado por essa mudança se ele ou as dependências dele usarem
reflexão de tempo de execução para espiar dentro de MessageQueue. Evite usar a reflexão de tempo de execução para inspecionar MessageQueue.
Com a implementação legada, os desenvolvedores às vezes acessavam campos particulares, como MessageQueue.mMessages, para inspecionar mensagens pendentes. Com a nova implementação sem bloqueio, as estruturas de dados internas mudaram completamente.
Para manter a compatibilidade binária, o Android 17 mantém o campo mMessages, mas na nova implementação, esse campo é sempre nulo, independente de haver mensagens na fila.
Além disso, se você usa algumas bibliotecas de teste conhecidas, será necessário atualizar
as bibliotecas para que sejam compatíveis com a nova implementação do MessageQueue.
Espresso
O Espresso é usado com frequência para testes de interface. A biblioteca Espresso precisa saber quando a linha de execução principal está inativa para fazer asserções corretas no estado da UI. As versões anteriores do Espresso dependiam de técnicas de reflexão que não são mais compatíveis com a MessageQueue sem bloqueio.
Ação
Atualize para o Espresso 3.7.0 ou mais recente. Esta versão usa a
API TestLooperManager, principalmente as novas APIs introduzidas pelo Android 16,
para interagir com segurança com o Looper sem depender de detalhes de implementação
internos.
Robolectric
Da mesma forma, se você executar testes de unidade usando o Robolectric, poderá encontrar problemas se seus testes dependerem do modo Looper legado.
Ação
Atualize para o Robolectric 4.17 ou mais recente. Se você estiver usando @LooperMode(LEGACY),
migre seus testes para o novo @LooperMode(PAUSED). Consulte o
guia de migração do Robolectric para mais informações.
Testar o comportamento
Você pode testar o app com a mudança de comportamento no Android 17 sem atualizar
targetSDK executando o seguinte comando:
adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>
Esse comando ativa o MessageQueue sem bloqueio no seu app, se ele for um build
depurável.
Se o app for destinado ao Android 17, o novo comportamento será ativado
por padrão. Se você notar um comportamento inesperado ou falhas após segmentar esse nível de API, desative temporariamente a nova implementação para verificar se MessageQueue é a causa.
É possível alternar a mudança usando uma destas duas opções:
O menu Mudanças na compatibilidade de apps em Opções do desenvolvedor.
Executando o seguinte comando ADB:
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
Isso reverte o app para a implementação legada baseada em bloqueio, permitindo que você identifique se o problema foi resultado de uma mudança no comportamento da fila de mensagens.