Podczas pracy z regułami przechowywania ważne jest, aby osiągnąć odpowiedni poziom szczegółowości, który zapewni korzyści przy jednoczesnym zachowaniu działania aplikacji. Więcej informacji o dobrych wzorcach i rzeczach, których należy unikać w regułach przechowywania, znajdziesz w tych sekcjach.
Dobre wzorce w regułach przechowywania
Dobrze zdefiniowane reguły przechowywania są jak najbardziej szczegółowe i zgodne z tymi wzorcami:
W specyfikacji klasy, jeśli to możliwe, zawsze określaj konkretną klasę, klasę bazową lub klasę z adnotacjami, jak pokazano w tych przykładach:
-keepclassmembers class com.example.MyClass { void someSpecificMethod(); }-keepclassmembers ** extends com.example.MyBaseClass { void someSpecificMethod(); }-keepclassmembers @com.example.MyAnnotation class ** { void someSpecificMethod(); }Jeśli to możliwe, używaj adnotacji w kodzie źródłowym, a następnie kieruj na te adnotacje bezpośrednio w regułach przechowywania. Tworzy to wyraźne, bezpośrednie połączenie między kodem a regułami, które go zachowują, dzięki czemu konfiguracja jest bardziej niezawodna, łatwiejsza do zrozumienia i mniej podatna na uszkodzenia w przypadku zmian w kodzie.
Na przykład ten fragment kodu pokazuje, jak zachować klasę MyClass oraz inne klasy, które mają adnotację
@com.example.DisplayComponent:// In the source code @com.example.DisplayComponent class MyClass { /* ... */ } // In the keep rules -keep @com.example.DisplayComponent class * {*;}Zalecamy nadawanie adnotacjom nazw, które zapewniają odpowiedni kontekst, dlaczego części kodu są zachowywane. Na przykład w aplikacji, w której komponenty wyświetlania wymagają zachowania niektórych części, użyj adnotacji
@DisplayComponent.Jeśli to możliwe, należy zadeklarować specyfikację elementu i odwoływać się tylko do tych części klasy, które muszą zostać zachowane, aby aplikacja działała. Nie zalecamy stosowania reguły do całej klasy przez zdefiniowanie opcjonalnego zakresu elementu jako
{ *; }, chyba że jest to bezwzględnie konieczne.-keepclassmembers com.example.MyClass { void someSpecificMethod(); void @com.example.MyAnnotation *; }Jeśli używasz opcji globalnej
repackageclassesunikaj określania opcjonalnej nazwy pakietu. Powoduje to zmniejszenie rozmiaru plików DEX, ponieważ w nazwach klas po zmianie pakietu pomijany jest prefiks pakietu.Zachowaj reguły przechowywania wszystkich elementów, do których uzyskiwany jest dostęp za pomocą odbicia. Nawet jeśli takie elementy są zachowywane przez R8 bez wyraźnych reguł przechowywania, zachowanie rzeczywistych reguł jest kluczowe, ponieważ przyszłe zmiany w kodzie mogą spowodować, że R8 nie będzie już zachowywać tych elementów.
W przypadku odbicia w Twoim kodzie możesz użyć Jetpack Keep, aby wygenerować reguły przechowywania, które są łatwiejsze w utrzymaniu. Każda adnotacja znajduje się w kodzie, który wykonuje odbicie, więc gdy zmienisz ten kod, zaktualizujesz lub usuniesz jego adnotację w tym samym miejscu. Dzięki temu reguły nie zachowują kodu, który nie jest już używany w aplikacji. Lint oznacza też wywołania odbicia, które nie mają adnotacji.
Jeśli to możliwe, używaj opcji
-assumenosideeffectslub-convertchecknotnull, aby zoptymalizować sprawdzanie wartości null, ponieważ może to znacznie zmniejszyć rozmiar pliku DEX aplikacji. Więcej informacji znajdziesz w sekcji Dodatkowe typy reguł.
Jeśli nie możesz przestrzegać tych wytycznych, możesz tymczasowo odizolować kod, który ma zostać zachowany, w osobnym pakiecie i zastosować do niego regułę przechowywania. Nie jest to jednak rozwiązanie długoterminowe. Więcej informacji znajdziesz w sekcji Stopniowe wdrażanie optymalizacji. Aby użyć reguły przechowywania dla pakietu, zdefiniuj ją tak jak w tym przykładzie:
-keepclassmembers class com.example.pkg.** { *; }
Czego warto unikać
Składnia reguł przechowywania ma wiele opcji, ale aby uzyskać wymierne i trwałe korzyści w zakresie wydajności, zalecamy nieużywanie tych opcji:
- Nie używaj długoterminowo reguł przechowywania obejmujących cały pakiet, takich jak
-keep class com.example.pkg.** { *; }. Można ich używać tymczasowo, aby obejść problemy podczas konfigurowania R8. Więcej informacji znajdziesz w sekcji Ograniczanie zakresu optymalizacji. Ogólnie rzecz biorąc, należy zachować ostrożność w przypadku symboli wieloznacznych – upewnij się, że zachowujesz tylko ten kod, którego potrzebujesz. - Jeśli to możliwe, unikaj bibliotek, które sugerują kopiowanie i wklejanie reguł przechowywania, zwłaszcza reguł obejmujących cały pakiet. Biblioteki zaprojektowane tak, aby działały dobrze na Androidzie, powinny w miarę możliwości unikać odbicia i w razie potrzeby osadzać reguły przechowywania dla konsumentów.
- Unikaj używania operatora negacji
!w regułach przechowywania, ponieważ możesz nieumyślnie zastosować regułę do prawie każdej klasy w aplikacji.
Jeśli nie możesz przestrzegać tych reguł, być może używasz wielu otwartych odbicia. W takim przypadku unikaj odbicia lub biblioteki, która go używa (patrz studium przypadku Gson).