Optimisation pour les auteurs de bibliothèques

En tant qu'auteur de bibliothèque, vous devez vous assurer que les développeurs d'applications peuvent facilement intégrer votre bibliothèque dans leur application tout en conservant une expérience utilisateur de haute qualité. Vous devez vous assurer que votre bibliothèque est compatible avec l'optimisation Android sans configuration supplémentaire, ou indiquer que la bibliothèque peut ne pas être adaptée à l'utilisation sur Android.

Cette documentation s'adresse aux développeurs de bibliothèques publiées, mais peut également être utile aux développeurs de modules de bibliothèque interne dans une grande application modulaire.

Si vous êtes développeur d'applications et que vous souhaitez découvrir comment optimiser votre application Android, consultez Activer l'optimisation des applications. Pour savoir quelles bibliothèques sont appropriées, consultez la section Choisir judicieusement des bibliothèques.

Utiliser le codegen plutôt que la réflexion

Dans la mesure du possible, utilisez la génération de code (codegen) plutôt que la réflexion. La génération de code et la réflexion sont deux approches courantes pour éviter le code standard lors de la programmation, mais la génération de code est plus compatible avec un optimiseur d'application tel que R8:

  • Avec le codegen, le code est analysé et modifié pendant le processus de compilation. Étant donné qu'il n'y a pas de modifications majeures après le temps de compilation, l'optimiseur sait quel code est finalement nécessaire et ce qui peut être supprimé en toute sécurité.
  • Avec la réflexion, le code est analysé et manipulé au moment de l'exécution. Étant donné que le code n'est pas vraiment finalisé tant qu'il ne s'exécute pas, l'optimiseur ne sait pas quel code peut être supprimé en toute sécurité. Il est probable qu'il supprime le code utilisé de manière dynamique via la réflexion au moment de l'exécution, ce qui entraîne des plantages de l'application pour les utilisateurs.

De nombreuses bibliothèques modernes utilisent la génération de code au lieu de la réflexion. Consultez KSP pour un point d'entrée commun, utilisé par Room, Dagger2 et bien d'autres.

Quand la réflexion est appropriée

Si vous devez utiliser la réflexion, vous ne devez la refléter que dans l'une des options suivantes:

  • Types ciblés spécifiques (implémentateurs d'interface ou sous-classes spécifiques)
  • Code utilisant une annotation d'exécution spécifique

L'utilisation de la réflexion de cette manière limite le coût d'exécution et permet d'écrire des règles de conservation ciblées pour les consommateurs.

Cette forme de réflexion spécifique et ciblée est un modèle que vous pouvez voir à la fois dans le framework Android (par exemple, lors de l'inflation d'activités, de vues et de drawables) et dans les bibliothèques AndroidX (par exemple, lors de la création de WorkManager ListenableWorkers ou de RoomDatabases). En revanche, la réflexion ouverte de Gson n'est pas adaptée à l'utilisation dans les applications Android.

Écrire des règles de conservation pour le consommateur

Les bibliothèques doivent empaqueter des règles de conservation "consommateur", qui utilisent le même format que les règles de conservation des applications. Ces règles sont regroupées dans des artefacts de bibliothèque (AAR ou JAR) et sont consommées automatiquement lors de l'optimisation de l'application Android lorsque la bibliothèque est utilisée.

Bibliothèques AAR

Pour ajouter des règles de consommation pour une bibliothèque AAR, utilisez l'option consumerProguardFiles dans le script de compilation du module de bibliothèque Android. Pour en savoir plus, consultez nos conseils pour créer des modules de bibliothèque.

Kotlin

android {
    defaultConfig {
        consumerProguardFiles("consumer-proguard-rules.pro")
    }
    ...
}

Groovy

android {
    defaultConfig {
        consumerProguardFiles 'consumer-proguard-rules.pro'
    }
    ...
}

Bibliothèques JAR

Pour regrouper des règles avec votre bibliothèque Kotlin/Java fournie sous forme de fichier JAR, placez votre fichier de règles dans le répertoire META-INF/proguard/ du fichier JAR final, avec un nom de fichier quelconque. Par exemple, si votre code est dans <libraryroot>/src/main/kotlin, placez un fichier de règles de consommation à <libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro. Les règles seront regroupées à l'emplacement approprié dans votre fichier JAR de sortie.

Vérifiez que le fichier JAR final regroupe correctement les règles en vérifiant qu'elles se trouvent dans le répertoire META-INF/proguard.

Prendre en charge différents outils de réduction (option avancée)

Vous pouvez adapter des règles à des réducteurs spécifiques (R8 ou ProGuard), ainsi qu'à des versions spécifiques de réducteurs. Cela permet à votre bibliothèque de fonctionner de manière optimale dans les projets qui utilisent de nouvelles versions de réduction, tout en permettant aux règles existantes de continuer à être utilisées dans les projets avec des versions plus anciennes de réduction.

Pour spécifier des règles de réduction ciblées, vous devez les inclure à des emplacements spécifiques dans une bibliothèque AAR ou JAR, comme décrit ci-dessous.

In an AAR library:
    consumer-proguard-rules.pro (legacy location)
    classes.jar
    └── META-INF
        └── com.android.tools (targeted shrink rules location)
            ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
            └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

In a JAR library:
    META-INF
    ├── proguard/<ProGuard-rules-file> (legacy location)
    └── com.android.tools (targeted shrink rules location)
        ├── r8-from-<X>-upto-<Y>/<R8-rules-file>
        └── proguard-from-<X>-upto-<Y>/<ProGuard-rules-file>

Cela signifie que les règles de réduction ciblée sont stockées dans le répertoire META-INF/com.android.tools d'un fichier JAR ou dans le répertoire META-INF/com.android.tools dans classes.jar d'un fichier AAR.

Sous ce répertoire, il peut y avoir plusieurs répertoires dont les noms sont au format r8-from-<X>-upto-<Y> ou proguard-from-<X>-upto-<Y> pour indiquer les versions de quel réducteur les règles des répertoires sont écrites. Notez que les parties -from-<X> et -upto-<Y> sont facultatives, que la version <Y> est exclusive et que les plages de versions doivent être continues.

Par exemple, r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0 et r8-from-8.2.0 constituent un ensemble valide de règles de réduction ciblée. Les règles du répertoire r8-from-8.0.0-upto-8.2.0 seront utilisées par R8 à partir de la version 8.0.0 jusqu'à la version 8.2.0 (non incluse).

Compte tenu de ces informations, le plug-in Android Gradle sélectionne les règles des répertoires R8 correspondants. Si une bibliothèque ne spécifie pas de règles de réduction ciblée, le plug-in Android Gradle sélectionnera les règles à partir des emplacements précédents (proguard.txt pour un fichier AAR ou META-INF/proguard/<ProGuard-rules-file> pour un fichier JAR).