Ottimizzazione per gli autori delle librerie

In qualità di autore della libreria, devi assicurarti che gli sviluppatori di app possano incorporare facilmente la tua libreria nella loro app mantenendo un'esperienza utente finale di alta qualità. Devi assicurarti che la tua libreria sia compatibile con l'ottimizzazione di Android senza configurazione aggiuntiva o documentare che la libreria potrebbe essere inappropriata per l'utilizzo su Android.

Questa documentazione è rivolta agli sviluppatori di librerie pubblicate, ma potrebbe essere utile anche per gli sviluppatori di moduli di librerie interne in un'app di grandi dimensioni e modularizzata.

Se sei uno sviluppatore di app e vuoi scoprire come ottimizzare la tua app per Android, consulta Attivare l'ottimizzazione delle app. Per scoprire quali librerie sono appropriate da utilizzare, consulta Scegliere le librerie con saggezza.

Utilizza codegen anziché la riflessione

Se possibile, utilizza la generazione di codice (codegen) anziché la riflessione. La generazione di codice e la riflessione sono entrambi approcci comuni per evitare il codice boilerplate durante la programmazione, ma la generazione di codice è più compatibile con un ottimizzatore di app come R8:

  • Con codegen, il codice viene analizzato e modificato durante il processo di compilazione. Poiché non vengono apportate modifiche sostanziali dopo il tempo di compilazione, l'ottimizzatore sa quale codice è necessario e cosa può essere rimosso in sicurezza.
  • Con la riflessione, il codice viene analizzato e manipolato in fase di esecuzione. Poiché il codice non viene effettivamente finalizzato finché non viene eseguito, lo strumento di ottimizzazione non sa quale codice puoi rimuovere in sicurezza. È probabile che venga rimosso il codice utilizzato dinamicamente tramite la riflessione durante l'esecuzione, causando arresti anomali dell'app per gli utenti.

Molte librerie moderne utilizzano la compilazione anziché la riflessione. Consulta KSP per un punto di contatto comune, utilizzato da Room, Dagger2 e molti altri.

Quando la riflessione è accettabile

Se devi utilizzare la riflessione, devi farlo solo in uno dei seguenti modi:

  • Tipi di target specifici (implementatori o sottoclassi dell'interfaccia specifici)
  • Codice che utilizza un'annotazione di runtime specifica

L'utilizzo della riflessione in questo modo limita il costo di runtime e consente di scrivere regole di conservazione dei consumatori target.

Questa forma specifica e mirata di riflessione è uno schema che puoi vedere sia nel framework Android (ad esempio durante l'inflazione di attività, visualizzazioni e drawable) sia nelle librerie AndroidX (ad esempio durante la creazione di WorkManager ListenableWorker o RoomDatabase). Al contrario, la riflessione aperta di Gson non è appropriata per l'utilizzo nelle app per Android.

Scrivere regole di conservazione per i consumatori

Le librerie devono pacchettizzare le regole di conservazione "consumer", che utilizzano lo stesso formato delle regole di conservazione delle app. Queste regole vengono raggruppate negli elementi della libreria (AAR o JAR) e vengono utilizzate automaticamente durante l'ottimizzazione dell'app per Android quando la libreria viene utilizzata.

Librerie AAR

Per aggiungere regole di consumo per una libreria AAR, utilizza l'opzione consumerProguardFiles nello script di compilazione del modulo della libreria Android. Per ulteriori informazioni, consulta le nostre linee guida per la creazione di moduli della libreria.

Kotlin

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

Groovy

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

Librerie JAR

Per raggruppare le regole con la libreria Kotlin/Java fornita come JAR, inserisci il file delle regole nella directory META-INF/proguard/ del JAR finale, con un nome file qualsiasi. Ad esempio, se il codice è in <libraryroot>/src/main/kotlin, inserisci un file di regole consumer in <libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro e le regole verranno raggruppate nella posizione corretta nel file JAR di output.

Verifica che il JAR finale combini correttamente le regole controllando che queste si trovino nella directory META-INF/proguard.

Supporta diversi compressori (avanzato)

Puoi personalizzare le regole in base a compressori specifici (R8 o ProGuard) come anche a versioni specifiche dei compressori. In questo modo, la libreria può funzionare in modo ottimale nei progetti che utilizzano le nuove versioni dello shrinker, consentendo al contempo di continuare a utilizzare le regole esistenti nei progetti con versioni precedenti dello shrinker.

Per specificare le regole di compressione mirate, devi includerle in posizioni specifiche all'interno di una libreria AAR o JAR, come descritto di seguito.

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>

Ciò significa che le regole di riduzione mirate vengono archiviate nella directory META-INF/com.android.tools di un file JAR o nella directory META-INF/com.android.tools all'interno di classes.jar di un file AAR.

In questa directory possono essere presenti più directory con nomi nel formato r8-from-<X>-upto-<Y> o proguard-from-<X>-upto-<Y> per indicare per quali versioni di quale compressore sono scritte le regole all'interno delle directory. Tieni presente che le parti -from-<X> e -upto-<Y> sono facoltative, la versione <Y> è esclusiva e gli intervalli di versione devono essere continui.

Ad esempio, r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0 e r8-from-8.2.0 formano un insieme valido di regole di riduzione mirate. Le regole nella directoryr8-from-8.0.0-upto-8.2.0 verranno utilizzate da R8 dalla versione 8.0.0 fino alla versione 8.2.0, esclusa.

In base a queste informazioni, il plug-in Android per Gradle seleziona le regole dalle directory R8 corrispondenti. Se una libreria non specifica regole di compressione mirate, il plug-in Gradle per Android seleziona le regole dalle posizioni precedenti (proguard.txt per un file AAR o META-INF/proguard/<ProGuard-rules-file> per un file JAR).