Cuando trabajes con reglas de conservación, es importante alcanzar el nivel de especificidad adecuado para asegurarte de obtener beneficios y, al mismo tiempo, mantener el comportamiento de tu app. Consulta las siguientes secciones para obtener información sobre los patrones adecuados y los elementos que debes evitar en las reglas de conservación.
Patrones adecuados en las reglas de conservación
Las reglas de conservación bien definidas son lo más específicas posible y cumplen con los siguientes patrones:
Para la especificación de clase, siempre especifica una clase específica, una clase base o una clase anotada si es posible, como se muestra en los siguientes ejemplos:
-keepclassmembers class com.example.MyClass { void someSpecificMethod(); }-keepclassmembers ** extends com.example.MyBaseClass { void someSpecificMethod(); }-keepclassmembers @com.example.MyAnnotation class ** { void someSpecificMethod(); }Siempre que sea posible, usa anotaciones en tu código fuente y, luego, segmenta esas anotaciones directamente en tus reglas de conservación. Esto crea un vínculo claro y explícito entre tu código y las reglas que lo conservan, lo que hace que tu configuración sea más sólida, fácil de comprender y menos propensa a fallas cuando se realizan cambios en el código.
Por ejemplo, en el siguiente fragmento, se muestra cómo puedes conservar la clase MyClass, así como otras clases que están anotadas con
@com.example.DisplayComponent:// In the source code @com.example.DisplayComponent class MyClass { /* ... */ } // In the keep rules -keep @com.example.DisplayComponent class * {*;}Te recomendamos que nombres tus anotaciones de manera que proporcionen un contexto significativo sobre por qué se conservan las partes del código. Por ejemplo, usa
@DisplayComponentpara una app en la que los componentes de visualización requieren que se conserven algunas partes.Siempre que sea posible, se debe declarar la especificación de miembro y solo hacer referencia a las partes de la clase que se deben conservar para que la app funcione. Se recomienda no aplicar una regla a una clase completa definiendo el alcance de miembro opcional como
{ *; }a menos que sea estrictamente necesario.-keepclassmembers com.example.MyClass { void someSpecificMethod(); void @com.example.MyAnnotation *; }Si usas la
repackageclassesopción global, evita especificar el nombre del paquete opcional. Esto genera archivos DEX más pequeños porque se omite el prefijo del paquete en los nombres de las clases reempaquetadas.Mantén las reglas de conservación para todos los elementos a los que se accede por reflexión. Incluso si R8 retiene esos elementos sin reglas de conservación explícitas, es fundamental mantener las reglas reales, ya que los cambios futuros en el código podrían hacer que R8 ya no retenga estos elementos.
Para la reflexión en tu propio código, puedes usar Jetpack Keep para generar reglas de conservación que sean más fáciles de mantener. Cada anotación está en el código que realiza la reflexión, por lo que, cuando cambias ese código, actualizas o quitas su anotación en el mismo lugar. De esa manera, las reglas no conservan el código que tu app ya no refleja. Lint también marca las llamadas reflexivas que no están anotadas.
Cuando sea posible, usa
-assumenosideeffectso-convertchecknotnullpara optimizar las verificaciones de valores nulos, ya que esto puede reducir significativamente el tamaño del DEX de tu app. Para obtener más información, consulta Tipos de reglas adicionales.
Si no puedes cumplir con estos lineamientos, puedes aislar temporalmente el código que se debe conservar en un paquete dedicado y aplicar tu regla de conservación al paquete. Sin embargo, esta no es una solución a largo plazo. Para obtener más información, consulta Adopta optimizaciones de forma incremental. Para usar una regla de conservación para un paquete, define una regla de conservación como se muestra en el siguiente ejemplo:
-keepclassmembers class com.example.pkg.** { *; }
Elementos que debes evitar
La sintaxis de la regla de conservación tiene muchas opciones, pero para obtener beneficios de rendimiento sostenibles y medibles, te recomendamos que no uses lo siguiente:
- No uses reglas de conservación en todo el paquete, como
-keep class com.example.pkg.** { *; }, a largo plazo. Se pueden usar de forma temporal para solucionar problemas cuando se configura R8. Para obtener más información, consulta Limita el alcance de la optimización. En general, ten cuidado con los comodines. Asegúrate de conservar solo el código que necesitas. - Cuando sea posible, evita las bibliotecas que te sugieren copiar y pegar reglas de conservación cuando las usas, en especial las reglas de conservación en todo el paquete. Las bibliotecas diseñadas para funcionar bien en Android deben evitar la reflexión cuando sea posible y si es necesario, incorporar reglas de conservación del consumidor.
- Evita usar el operador de inversión
!en las reglas de conservación, ya que podrías aplicar una regla de forma involuntaria a casi todas las clases de tu aplicación.
Si no puedes seguir estas reglas, es posible que estés usando mucha reflexión abierta y debes evitar la reflexión o la biblioteca que usa la reflexión (consulta el caso de éxito de Gson).