Por padrão, o R8 faz muitas otimizações para melhorar o desempenho e o tamanho, mas elas podem não funcionar imediatamente no seu app. Se você estiver ativando o R8 (ou o modo completo) em um app grande pela primeira vez, tente adotar otimizações incrementais: desative temporariamente a ofuscação e ative o R8 para partes do código por vez, em vez de todo o código no app. Recomendamos essa abordagem incremental durante o desenvolvimento local, mas você também pode usá-la durante testes de controle de qualidade interno ou até mesmo na produção como um lançamento gradual. As etapas exatas que você toma dependem do cronograma desejado e da confiança na cobertura de testes de pré-lançamento.
Limitar as otimizações
O R8 faz muitos tipos de otimizações, incluindo a remoção de código, a reescrita de código e a remoção de recursos. Confira algumas descrições gerais dos tipos de otimização:
- Redução de código (ou tree shaking): remove o código sem referência
- Ofuscação (ou minimização de identificador): encurta os nomes de classes e métodos.
- Otimização: reescreve o código, por exemplo, inline
Para reduzir a chance de erros, comece ativando apenas algumas dessas otimizações.
Ativar somente a agitação de árvore
A redução de código, também conhecida como tree shaking, remove o código que parece não ter referências. Recomendamos começar com a agitação de árvores, porque é a mais simples.
Para ativar apenas a agitação de árvore, adicione o seguinte ao
arquivo proguard-rules.pro
para desativar os outros tipos de otimizações. Desabilitar
a ofuscação é fundamental porque facilita a leitura dos rastros de pilha.
-dontobfuscate // Use temporarily to turn off identifier minification
-dontoptimize // Use temporarily to turn off optimization
No final, não é recomendável enviar essa configuração, já que ela limita drasticamente a capacidade do R8 de otimizar o código, mas é um ótimo ponto de partida ao adotar o R8 pela primeira vez em uma base de código grande com problemas a serem corrigidos.
Usar o modo compatível
Por padrão, o R8 é executado no modo completo. O modo completo melhora significativamente o desempenho e a economia de tamanho, mas você pode desativá-lo temporariamente e usar o modo compatível ao ativar a minificação pela primeira vez.
Para usar o modo de compatibilidade, use a seguinte configuração no arquivo gradle.properties
:
android.enableR8.fullMode = false // Use temporarily to disable full mode
Ativar o restante das otimizações
Depois de confirmar que a agitação de árvore funciona no app, remova as configurações anteriores para reativar a ofuscação, a otimização e o modo completo do R8. A ofuscação pode dificultar a depuração. Por isso, recomendamos resolver os problemas de agitação de árvore primeiro.
Para mais informações sobre como desofuscar stack traces, consulte Recuperar o stack trace original.
Limitar o escopo da otimização
Um build totalmente otimizado otimiza todo o código em todas as bibliotecas e pacotes. Por isso, é comum encontrar problemas com o R8 quando você o ativa pela primeira vez. Se você encontrar um problema de otimização em uma parte do app, não desative o R8 completamente ou perderá os benefícios em todos os outros lugares. Em vez disso, desative temporariamente o R8 apenas nas partes do app que estão causando problemas.
Usar regras de retenção em todo o pacote
Recomendamos o uso de regras de manutenção em todo o pacote como uma maneira de desativar temporariamente o R8 em partes do app. Sempre volte para corrigir esses problemas de otimização mais tarde. Essa é geralmente uma solução temporária para contornar áreas problemáticas.
Por exemplo, se parte do app usa muito o Gson e está causando problemas com
otimização, a correção ideal é adicionar mais
regras de keep direcionadas ou mudar para uma solução de geração de código. No entanto, para desbloquear a otimização do restante do app, você pode colocar o código que define seus
tipos Gson em um subpacote dedicado e adicionar uma regra como esta ao
arquivo proguard-rules.pro
:
-keep class com.myapp.json.** { *; }
Se alguma biblioteca que você está usando tiver reflexão em componentes internos, você poderá adicionar uma regra de manutenção para toda a biblioteca. Você precisa inspecionar o código da biblioteca ou o JAR/AAR para encontrar o pacote adequado para manter. Novamente, não é recomendável manter isso a longo prazo, mas pode desbloquear a otimização do restante do app:
-keep class com.somelibrary.** { *; }
Remover regras de retenção em todo o pacote
Depois que o app funcionar corretamente com regras de keep em todo o pacote, volte e adicione regras de keep específicas ou remova o uso de reflexão ou a biblioteca que exige a regra de keep.
Por exemplo, manter todas as regras que estendem uma determinada classe é extremamente comum no AndroidX para manter apenas as classes relevantes. Geralmente, a reflexão precisa ser direcionada apenas a classes ou métodos que estendem determinadas classes abstratas, implementam determinadas interfaces ou a classes com uma anotação de tempo de execução específica. Cada uma delas é uma forma com suporte para definir regras de manutenção para que você não precise de regras de manutenção em todo o pacote no app final totalmente otimizado.