Suivre les bonnes pratiques

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 et respectent les modèles suivants :

  • 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, puis 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, l'extrait suivant montre comment conserver la classe MyClass, ainsi que d'autres classes annotées avec @com.example.DisplayComponent :

    // In the source code
    @com.example.DisplayComponent
    class MyClass { /* ... */ }
    
    // In the keep rules
    -keep @com.example.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.

  • Conservez les règles de conservation pour tous les éléments auxquels vous accédez par réflexion. Même si R8 conserve ces éléments sans règles de conservation explicites, il est essentiel de maintenir les règles réelles, car de futures modifications du code pourraient entraîner la non-conservation de ces éléments par R8.

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 :

  • 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.
  • Dans la mesure du possible, évitez les bibliothèques qui vous suggèrent de copier et coller des règles Keep lorsque vous les utilisez, en particulier les règles Keep à l'échelle du package. Les bibliothèques conçues pour fonctionner correctement sur Android doivent éviter la réflexion dans la mesure du possible et intégrer des règles de conservation des consommateurs si nécessaire.
  • É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.

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