Domyślnie R8 wykonuje wiele optymalizacji, aby zwiększyć wydajność i zmniejszyć rozmiar aplikacji, ale optymalizacje te mogą nie zadziałać od razu. Jeśli po raz pierwszy włączasz R8 (lub włączasz tryb pełny) w dużej aplikacji, spróbuj stosować optymalizacje stopniowo: tymczasowo wyłącz zaciemnianie i włącz R8 w poszczególnych częściach kodu, a nie w całym kodzie aplikacji. Zalecamy stosowanie tego podejścia stopniowego podczas lokalnego tworzenia aplikacji, ale możesz też stosować je podczas wewnętrznych testów jakości lub nawet w wersji produkcyjnej jako stopniowe wdrażanie. Dokładne czynności zależą od wybranego harmonogramu i poziomu pewności co do zakresu testowania przed opublikowaniem.
Ograniczanie optymalizacji
R8 wykonuje wiele rodzajów optymalizacji, w tym usuwanie kodu, przepisywanie kodu i usuwanie zasobów. Oto ogólny opis typów optymalizacji:
- zmniejszanie kodu (czyli usuwanie nieodwołującego się kodu),
- Zaciemnianie (czyli minimalizacja identyfikatorów): skraca nazwy klas i metod.
- Optymalizacja: przepisuje kod, np. wstawiając go w tekście.
Aby zmniejszyć ryzyko wystąpienia błędów, możesz zacząć od włączenia tylko niektórych z tych optymalizacji.
Włącz tylko potrząsanie drzewa
Zmniejszenie kodu, czyli tzw. tree shaking, usuwa kod, który wydaje się nieodwoływać do innych elementów. Zalecamy rozpoczęcie od potrząsania drzewem, ponieważ jest to najprostsza metoda.
Aby włączyć tylko wstrząsanie drzewa, dodaj do pliku proguard-rules.pro
ten kod, aby wyłączyć inne typy optymalizacji. Wyłączenie zaciemnienia jest kluczowe, ponieważ znacznie ułatwia odczytywanie dzienników błędów.
-dontobfuscate // Use temporarily to turn off identifier minification
-dontoptimize // Use temporarily to turn off optimization
Nie zalecamy używania tej konfiguracji, ponieważ znacznie ogranicza ona możliwości optymalizacji kodu przez R8. Jest to jednak świetny punkt wyjścia, jeśli po raz pierwszy używasz R8 w dużej bazie kodu, w której występują problemy wymagające rozwiązania.
Używanie trybu zgodności
Domyślnie R8 działa w trybie pełnym. Tryb pełny zapewnia znacznie lepszą wydajność i oszczędność miejsca, ale możesz go tymczasowo wyłączyć i zamiast niego użyć trybu zgodności, gdy po raz pierwszy włączysz kompresję.
Aby korzystać z trybu zgodności, użyj tego ustawienia w pliku gradle.properties
:
android.enableR8.fullMode = false // Use temporarily to disable full mode
Włącz pozostałe optymalizacje
Gdy potwierdzisz, że w przypadku Twojej aplikacji działa potrząsanie drzewa, możesz usunąć poprzednie ustawienia, aby ponownie włączyć zaciemnianie, optymalizację i tryb pełny R8. Pamiętaj, że zaciemnianie może utrudniać debugowanie, dlatego zalecamy najpierw rozwiązanie problemów z tree shakingiem.
Więcej informacji o usuwaniu zaciemnienia kodu ze zrzutów stosu znajdziesz w artykule Odzyskiwanie oryginalnego zrzutu stosu.
Ograniczanie zakresu optymalizacji
Pełna optymalizacja kompilacji optymalizuje cały kod we wszystkich bibliotekach i pakietach, dlatego często podczas włączania R8 występują problemy. Jeśli zauważysz problem z optymalizacją w jednej części aplikacji, nie wyłączaj R8 całkowicie, ponieważ utracisz korzyści w innych częściach. Zamiast tego tymczasowo wyłącz R8 tylko w tych częściach aplikacji, które powodują problemy.
Korzystanie z reguł przechowywania w całym pakiecie
Zalecamy używanie reguł zachowania na poziomie pakietu, aby tymczasowo wyłączyć R8 w niektórych częściach aplikacji. Zawsze należy później wrócić do tych problemów z optymalizacją. Jest to zazwyczaj tymczasowe rozwiązanie, które pozwala obejść problemowe obszary.
Jeśli na przykład część aplikacji intensywnie korzysta z Gson i powoduje problemy z optymalizacją, idealnym rozwiązaniem jest dodanie większej liczby reguł keep z użyciem filtra lub przejście na rozwiązanie codegen. Aby jednak odblokować optymalizację reszty aplikacji, możesz umieścić kod definiujący typy Gson w dedykowanym podpakiecie i dodać do pliku proguard-rules.pro
taką regułę:
-keep class com.myapp.json.** { *; }
Jeśli jakaś biblioteka, której używasz, zawiera refleksje na wewnętrzne komponenty, możesz podobnie dodać regułę zachowania dla całej biblioteki. Aby znaleźć odpowiedni pakiet, musisz sprawdzić kod biblioteki lub plik JAR/AAR. Ponownie przypominamy, że nie zalecamy stosowania tego rozwiązania na dłuższą metę, ale może ono odblokować optymalizację reszty aplikacji:
-keep class com.somelibrary.** { *; }
Usuwanie reguł przechowywania dotyczących całego pakietu
Gdy aplikacja będzie działać prawidłowo z zasadami Keep dotyczącymi całego pakietu, wróć i dodaj wybrane zasady Keep lub usuń użycie odbicia lustrzanego lub bibliotekę, które wymagają zasady Keep.
Na przykład w AndroidX bardzo często zachodzi potrzeba zachowania wszystkich reguł, które rozszerzają określone zajęcia, aby zachować tylko odpowiednie zajęcia. Ogólnie rzecz biorąc, mechanizm odbicia powinien dotyczyć tylko klas lub metod, które rozszerzają określone klasy abstrakcyjne, implementują określone interfejsy lub są klasami z określonymi adnotacjami czasu wykonywania. Każdy z tych sposobów jest obsługiwany w definiowaniu reguł zachowania, dzięki czemu nie musisz stosować reguł zachowania dotyczących całego pakietu w ostatecznej, w pełni zoptymalizowanej aplikacji.