Gdy włączysz optymalizację aplikacji, domyślne działanie optymalizatora będzie się różnić w zależności od wersji R8.
- W przypadku zaktualizowanego języka DSL, który jest dostępny w AGP 9.3 i nowszych wersjach, zmniejszanie zasobów jest domyślnie włączone, gdy włączona jest optymalizacja. Pamiętaj, że starsza wersja DSL, która wymaga wyraźnego włączenia optymalizacji kodu i zasobów, jest nadal obsługiwana.
W przypadku wersji starszych niż AGP 9.3 ustawienie
isShrinkResources = truenakazuje optymalizatorowi usunięcie nieużywanych zasobów, co pomaga zmniejszyć rozmiar aplikacji. Zmniejszanie zasobów działa tylko w połączeniu ze zmniejszaniem kodu, więc jeśli optymalizujesz zasoby, ustaw teżisMinifyEnabled = true.
AGP 9.3+ (Kotlin)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
AGP 9.3+ (Groovy)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
Starsza wersja DSL (Kotlin)
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
Starsza wersja DSL (Groovy)
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
...
}
}
Jeśli chcesz zachować lub odrzucić określone zasoby, utwórz w zasobach projektu plik XML keep, np. res/raw/keep_my_package.xml. Plik keep
zawiera te komponenty:
- Tag
<resources>– zawiera wszystkie elementy zasobów podrzędnych oraz atrybuty keep/discard. - Atrybut
tools:keep– akceptuje rozdzieloną przecinkami listę nazw zasobów, które mają zostać zachowane. - Atrybut
tools:discard– akceptuje rozdzieloną przecinkami listę nazw zasobów, które identyfikują zasoby do odrzucenia.
Użyj gwiazdki jako symbolu wieloznacznego, aby odwołać się do wielu zasobów w tym samym folderze, np.:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
Określanie, które zasoby mają zostać odrzucone, może wydawać się zbędne, skoro można je usunąć, ale odrzucanie zasobów może być przydatne w przypadku korzystania z wariantów kompilacji.
Kierowanie na określone warianty kompilacji
Aby usunąć zasoby tylko w niektórych wariantach kompilacji, umieść wszystkie zasoby w wspólnym katalogu projektu, a następnie utwórz inny plik keep_my_package_build_variant.xml dla każdego wariantu kompilacji w katalogu zasobów wariantu. W pliku keep ręcznie określ zasoby do usunięcia, gdy dany zasób wydaje się być używany w kodzie (a więc nie jest usuwany przez narzędzie do zmniejszania rozmiaru), ale wiesz, że w przypadku danego wariantu kompilacji nie będzie on używany.
Usuwanie nieużywanych zasobów alternatywnych
Optymalizator usuwa tylko zasoby, do których nie odwołuje się kod aplikacji, co oznacza, że nie usuwa alternatywnych zasobów dla różnych konfiguracji urządzeń.
Użyj właściwości resConfigs Androida Gradle w pliku build.gradle modułu aplikacji, aby usunąć zasoby alternatywne, których aplikacja nie potrzebuje.
Jeśli na przykład używasz biblioteki, która zawiera zasoby językowe (np. Usługi Google Play), Twoja aplikacja będzie zawierać wszystkie przetłumaczone ciągi tekstowe komunikatów w tych bibliotekach, niezależnie od tego, czy reszta aplikacji jest przetłumaczona na te same języki. Aby zachować tylko języki, które Twoja aplikacja oficjalnie obsługuje, określ je za pomocą właściwości resConfigs.
Wszystkie zasoby w językach, które nie zostały określone, zostaną usunięte.
Poniższe fragmenty kodu pokazują, jak ograniczyć zasoby językowe tylko do języka angielskiego i francuskiego:
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
lub
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
Gdy publikujesz aplikację w formacie pakietu aplikacji na Androida (AAB), domyślnie podczas instalowania aplikacji przez użytkownika pobierane są tylko języki skonfigurowane na jego urządzeniu. Podobnie w pobranych plikach znajdują się tylko zasoby pasujące do gęstości ekranu urządzenia i biblioteki natywne pasujące do interfejsu ABI urządzenia. Więcej informacji znajdziesz w artykule Ponowne włączanie i wyłączanie typów plików APK konfiguracji.
W przypadku starszych aplikacji (utworzonych przed sierpniem 2021 roku) wydawanych z plikami APK możesz dostosować gęstość ekranu lub zasoby ABI, które mają być uwzględnione w pliku APK, tworząc wiele plików APK przeznaczonych dla różnych konfiguracji urządzeń.
Unikanie konfliktów podczas scalania zasobów
Domyślnie wtyczka Androida do obsługi Gradle (AGP) scala zasoby o identycznych nazwach, np. elementy rysowalne o tej samej nazwie, które znajdują się w różnych folderach zasobów.
To zachowanie nie jest kontrolowane przez właściwość shrinkResources i nie można go wyłączyć, ponieważ jest ono niezbędne, aby uniknąć błędów, gdy wiele zasobów ma nazwę, do której odwołuje się kod.
Scalanie zasobów następuje tylko wtedy, gdy co najmniej 2 pliki mają identyczną nazwę, typ i kwalifikator zasobu. AGP wybiera plik, który uzna za najlepszy spośród duplikatów (na podstawie kolejności priorytetów opisanej poniżej), i przekazuje tylko ten zasób do AAPT w celu dystrybucji w końcowym artefakcie kompilacji.
Wtyczka Androida do obsługi Gradle szuka zduplikowanych zasobów w tych lokalizacjach:
- Główne zasoby powiązane z głównym zbiorem źródeł, zwykle znajdujące się w folderze
src/main/res/ - Nakładki wariantów z rodzaju kompilacji i wersji kompilacji.
- Zależności projektu biblioteki
Wtyczka Androida do obsługi Gradle scala zduplikowane zasoby w tej kolejności priorytetów:
Jeśli na przykład zduplikowany zasób występuje zarówno w zasobach głównych, jak i w wersji kompilacji, Gradle wybierze zasób w wersji kompilacji.
Jeśli identyczne zasoby pojawią się w tym samym zestawie źródeł, Gradle nie będzie w stanie ich scalić i wygeneruje błąd scalania zasobów. Może się tak zdarzyć, jeśli w właściwości sourceSet pliku modułu build.gradle zdefiniujesz wiele zestawów źródeł, np. jeśli zarówno src/main/res/, jak i src/main/res2/ zawierają identyczne zasoby.
Rozwiązywanie problemów ze zmniejszaniem zasobów
Po zmniejszeniu zasobów w oknie Kompilacja pojawi się podsumowanie zasobów usuniętych z aplikacji. (Aby wyświetlić szczegółowe dane wyjściowe Gradle, po lewej stronie okna kliknij Przełącz widok). Przykład:
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
Gradle tworzy też plik diagnostyczny o nazwie resources.txt w katalogu <module-name>/build/outputs/mapping/release/ (tym samym, w którym znajdują się pliki wyjściowe ProGuard). Plik zawiera szczegóły, takie jak informacje o tym, które zasoby odwołują się do innych zasobów, oraz które zasoby są używane lub usuwane.
Aby na przykład dowiedzieć się, dlaczego plik @drawable/ic_plus_anim_016 nadal znajduje się w aplikacji, otwórz plik resources.txt i wyszukaj tę nazwę. Może się okazać, że
odwołuje się do niego inny zasób:
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
Musisz teraz wiedzieć, dlaczego adres @drawable/add_schedule_fab_icon_anim jest osiągalny. Jeśli wyszukasz w górę, znajdziesz ten zasób na liście pod nagłówkiem Główne osiągalne zasoby to: w sekcji resources.txt.
Oznacza to, że w kodzie jest odwołanie do add_schedule_fab_icon_anim, czyli w osiągalnym kodzie znaleziono jego R.drawable.
Jeśli nie używasz ścisłego sprawdzania, identyfikatory zasobów mogą być oznaczone jako dostępne, jeśli istnieją stałe ciągi znaków, które mogą być używane do tworzenia nazw zasobów w przypadku zasobów ładowanych dynamicznie. W takim przypadku, jeśli w wyniku kompilacji wyszukasz nazwę zasobu, możesz znaleźć komunikat podobny do tego:
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
used because its format-string matches string pool constant ic_plus_anim_%1$d.
Jeśli widzisz jeden z tych ciągów znaków i masz pewność, że nie jest on używany do dynamicznego wczytywania danego zasobu, użyj atrybutu tools:discard w pliku keep, aby poinformować system kompilacji o konieczności usunięcia zasobu.