Работая с правилами Keep, важно достичь необходимого уровня специфичности, чтобы получить преимущества, сохраняя при этом функциональность приложения. В следующих разделах вы найдете информацию о хороших шаблонах и о том, чего следует избегать при использовании правил Keep.
Хорошие образцы в правилах хранения
Четко определенные правила хранения максимально конкретны:
Для спецификации класса всегда указывайте конкретный класс, базовый класс или аннотированный класс, если это возможно, как показано в следующих примерах:
-keepclassmembers class com.example.MyClass { void someSpecificMethod(); }
-keepclassmembers ** extends com.example.MyBaseClass { void someSpecificMethod(); }
-keepclassmembers @com.example.MyAnnotation class ** { void someSpecificMethod(); }
По возможности используйте аннотации в исходном коде (например, аннотацию
@Keep
), а затем укажите эти аннотации непосредственно в правилах Keep. Это создаст чёткую и явную связь между вашим кодом и правилами, которые его сохраняют, делая конфигурацию более надёжной, понятной и менее подверженной сбоям при изменении кода.Например, библиотеки типа
androidx.annotation
используют этот шаблон:// In your source code @Keep class MyDataClass { /* ... */ } // In your R8 rules -keep @androidx.annotation.DisplayComponent class * {*;}
Мы рекомендуем называть аннотации так, чтобы они содержали содержательное описание того, почему сохраняются части кода. Например, используйте
@DisplayComponent
для приложения, в котором компоненты отображения требуют сохранения некоторых частей.По возможности следует объявлять спецификацию члена и ссылаться только на те части класса, которые необходимо сохранить для функционирования приложения. Рекомендуется не применять правило ко всему классу, определяя необязательную область действия члена как
{ *; }
за исключением случаев крайней необходимости.-keepclassmembers com.example.MyClass { void someSpecificMethod(); void @com.example.MyAnnotation *; }
При использовании глобальной опции
repackageclasses
не указывайте необязательное имя пакета. Это приводит к уменьшению размера DEX-файлов, поскольку префикс пакета опускается в именах переупакованных классов.
Если вы не можете следовать этим рекомендациям, вы можете временно изолировать код, который необходимо сохранить, в отдельном пакете и применить к нему правило сохранения. Однако это не является долгосрочным решением. Подробнее см. в разделе «Постепенное внедрение оптимизаций» . Чтобы использовать правило сохранения для пакета, определите его, как показано в следующем примере:
-keepclassmembers class com.example.pkg.** { *; }
Чего следует избегать
Синтаксис правила сохранения имеет много вариантов, но для достижения ощутимых преимуществ в плане устойчивой производительности мы рекомендуем не использовать следующие варианты:
- Избегайте использования оператора инверсии
!
в правилах keep, поскольку вы можете непреднамеренно применить правило практически к каждому классу в вашем приложении. - Не используйте правила сохранения для всего пакета, такие как
-keep class com.example.pkg.** { *; }
в долгосрочной перспективе. Их можно использовать временно для обхода проблем при настройке R8. Подробнее см. в разделе Ограничение области оптимизации . В целом, будьте осторожны с подстановочными знаками — убедитесь, что вы сохраняете только необходимый код.
Если вы не можете следовать этим правилам, возможно, вы слишком много используете открытую рефлексию, и вам следует либо избегать рефлексии, либо избегать библиотеки, использующей рефлексию (см. пример Gson ).