Optimización para autores de bibliotecas

Como autor de la biblioteca, debes asegurarte de que los desarrolladores de apps puedan incorporarla fácilmente en sus apps y, al mismo tiempo, mantener una experiencia del usuario final de alta calidad. Debes asegurarte de que tu biblioteca sea compatible con la optimización de Android sin configuración adicional, o bien documentar que la biblioteca podría ser inadecuada para su uso en Android.

Esta documentación está dirigida a desarrolladores de bibliotecas publicadas, pero también puede ser útil para desarrolladores de módulos de bibliotecas internas en una app grande y modularizada.

Si eres desarrollador de apps y quieres obtener información para optimizar tu app para Android, consulta Cómo habilitar la optimización de apps. Para obtener información sobre las bibliotecas que es apropiado usar, consulta Elige las bibliotecas con prudencia.

Usa codegen en lugar de reflexión

Cuando sea posible, usa la generación de código (codegen) en lugar de la reflexión. La generación de código y la reflexión son enfoques comunes para evitar el código de plantillas cuando se programa, pero la generación de código es más compatible con un optimizador de apps como R8:

  • Con codegen, el código se analiza y modifica durante el proceso de compilación. Como no hay modificaciones importantes después del tiempo de compilación, el optimizador sabe qué código se necesita en última instancia y qué se puede quitar de forma segura.
  • Con la reflexión, el código se analiza y manipula durante el tiempo de ejecución. Como el código realmente no se finaliza hasta que se ejecuta, el optimizador no sabe qué código se puede quitar de forma segura. Es probable que quite el código que se usa de forma dinámica a través de la reflexión durante el tiempo de ejecución, lo que causa fallas en la app para los usuarios.

Muchas bibliotecas modernas usan codegen en lugar de reflexión. Consulta KSP para obtener un punto de entrada común que usan Room, Dagger2 y muchos otros.

Cuándo se permite la reflexión

Si debes usar la reflexión, solo debes reflejar en cualquiera de las siguientes opciones:

  • Tipos de segmentación específicos (implementadores de interfaz o subclases específicos)
  • Código con una anotación de entorno de ejecución específica

El uso de la reflexión de esta manera limita el costo del tiempo de ejecución y permite escribir reglas de retención de consumidores segmentados.

Esta forma específica y segmentada de reflexión es un patrón que puedes ver en el framework de Android (por ejemplo, cuando se expanden actividades, vistas y elementos de diseño) y en las bibliotecas de AndroidX (por ejemplo, cuando se construyen WorkManager ListenableWorkers o RoomDatabases). Por el contrario, la reflexión abierta de Gson no es adecuada para su uso en apps para Android.

Cómo escribir reglas de retención del consumidor

Las bibliotecas deben empaquetar reglas de retención de "consumidor", que usan el mismo formato que las reglas de retención de apps. Estas reglas se agrupan en artefactos de bibliotecas (AAR o JAR) y se consumen automáticamente durante la optimización de apps para Android cuando se usa la biblioteca.

Bibliotecas AAR

Para agregar reglas de consumidor para una biblioteca AAR, usa la opción consumerProguardFiles en la secuencia de comandos de compilación del módulo de biblioteca de Android. Para obtener más información, consulta nuestra guía para crear módulos de biblioteca.

Kotlin

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

Groovy

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

Bibliotecas JAR

Para agrupar reglas con tu biblioteca de Kotlin/Java que se envía como un archivo JAR, coloca el archivo de reglas en el directorio META-INF/proguard/ del archivo JAR final, con cualquier nombre de archivo. Por ejemplo, si tu código está en <libraryroot>/src/main/kotlin, coloca un archivo de reglas de consumidor en <libraryroot>/src/main/resources/META-INF/proguard/consumer-proguard-rules.pro y las reglas se agruparán en la ubicación correcta en tu JAR de salida.

Verifica que el JAR final combine las reglas correctamente. Para ello, comprueba que las reglas se encuentren en el directorio META-INF/proguard.

Admite diferentes reductoras (avanzadas)

Puedes adaptar las reglas para que se orienten a reductoras específicas (R8 o ProGuard), así como a versiones específicas de reductoras. Esto permite que tu biblioteca funcione de manera óptima en proyectos que usan versiones nuevas del reductor, a la vez que permite que las reglas existentes se sigan usando en proyectos con versiones anteriores del reductor.

Para especificar reglas de reducción segmentadas, debes incluirlas en ubicaciones específicas dentro de una biblioteca AAR o JAR, como se describe a continuación.

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>

Eso significa que las reglas de reducción segmentadas se almacenan en el directorio META-INF/com.android.tools de un archivo JAR o en el directorio META-INF/com.android.tools dentro de classes.jar de un AAR.

En ese directorio, puede haber varios directorios con nombres en forma de r8-from-<X>-upto-<Y> o proguard-from-<X>-upto-<Y> para indicar para qué versiones de qué reductor se escribieron las reglas dentro de los directorios. Ten en cuenta que las partes -from-<X> y -upto-<Y> son opcionales, la versión <Y> es exclusiva y los rangos de versiones deben ser continuos.

Por ejemplo, r8-upto-8.0.0, r8-from-8.0.0-upto-8.2.0 y r8-from-8.2.0 forman un conjunto válido de reglas de reducción segmentadas. R8 usará las reglas del directorio r8-from-8.0.0-upto-8.2.0 desde la versión 8.0.0 hasta la versión 8.2.0, sin incluirla.

Con esa información, el complemento de Android para Gradle selecciona las reglas de los directorios de R8 que coinciden. Si una biblioteca no especifica reglas de reducción segmentadas, el complemento de Android para Gradle seleccionará las reglas de las ubicaciones heredadas (proguard.txt para un AAR o META-INF/proguard/<ProGuard-rules-file> para un JAR).