Lorsque vous travaillez avec des règles de conservation, il est important d'atteindre le bon niveau de spécificité pour vous assurer de bénéficier des avantages tout en conservant le comportement de votre application. Consultez les sections suivantes pour découvrir les bonnes pratiques et les éléments à éviter dans les règles de conservation.
Bonnes pratiques concernant les règles de conservation
Les règles de conservation bien définies sont aussi spécifiques que possible :
Pour la spécification de classe, spécifiez toujours une classe spécifique, une classe de base ou une classe annotée si possible, comme indiqué dans les exemples suivants :
-keepclassmembers class com.example.MyClass { void someSpecificMethod(); }
-keepclassmembers ** extends com.example.MyBaseClass { void someSpecificMethod(); }
-keepclassmembers @com.example.MyAnnotation class ** { void someSpecificMethod(); }
Dans la mesure du possible, utilisez des annotations dans votre code source (comme une annotation
@Keep
) et ciblez-les directement dans vos règles de conservation. Cela crée un lien clair et explicite entre votre code et les règles qui le préservent, ce qui rend votre configuration plus robuste, plus facile à comprendre et moins sujette aux erreurs lorsque le code change.Par exemple, les bibliothèques telles que
androidx.annotation
utilisent ce modèle :// In your source code @Keep class MyDataClass { /* ... */ } // In your R8 rules -keep @androidx.annotation.DisplayComponent class * {*;}
Nous vous recommandons de nommer vos annotations de manière à fournir un contexte pertinent expliquant pourquoi certaines parties du code sont conservées. Par exemple, utilisez
@DisplayComponent
pour une application dont les composants d'affichage nécessitent de conserver certaines parties.Dans la mesure du possible, la spécification des membres doit être déclarée et ne faire référence qu'aux parties de la classe qui doivent être conservées pour que l'application fonctionne. Il est recommandé de ne pas appliquer de règle à une classe entière en définissant le champ d'application du membre facultatif sur
{ *; }
, sauf si cela est strictement nécessaire.-keepclassmembers com.example.MyClass { void someSpecificMethod(); void @com.example.MyAnnotation *; }
Si vous utilisez l'option globale
repackageclasses
, évitez de spécifier le nom de package facultatif. Cela permet d'obtenir des fichiers DEX plus petits, car le préfixe du package est omis dans les noms de classes reconditionnés.
Si vous ne pouvez pas respecter ces consignes, vous pouvez isoler temporairement le code à conserver dans un package dédié et appliquer votre règle de conservation au package. Toutefois, il ne s'agit pas d'une solution à long terme. Pour en savoir plus, consultez Adopter les optimisations de manière incrémentielle. Pour utiliser une règle de conservation pour un package, définissez-la comme indiqué dans l'exemple suivant :
-keepclassmembers class com.example.pkg.** { *; }
Ce qu'il faut éviter
La syntaxe des règles de conservation offre de nombreuses options, mais pour obtenir des avantages mesurables en termes de performances durables, nous vous recommandons de ne pas utiliser les options suivantes :
- Évitez d'utiliser l'opérateur d'inversion
!
dans les règles Keep, car vous pourriez appliquer involontairement une règle à presque toutes les classes de votre application. - N'utilisez pas de règles de conservation à l'échelle du package, telles que
-keep class com.example.pkg.** { *; }
, à long terme. Ils peuvent être utilisés temporairement pour contourner les problèmes lors de la configuration de R8. Pour en savoir plus, consultez Limiter le champ d'application de l'optimisation. En règle générale, soyez prudent avec les caractères génériques. Assurez-vous de ne conserver que le code dont vous avez besoin.
Si vous ne parvenez pas à suivre ces règles, vous utilisez peut-être beaucoup de réflexion ouverte. Vous devez alors éviter la réflexion ou la bibliothèque utilisant la réflexion (voir l'étude de cas Gson).