W miarę jak nasze aplikacje dodają nowe funkcje i stają się coraz bardziej złożone, często zdarza się, że rozmiar pliku końcowego znacznie wzrasta. To poważny problem, ponieważ jeśli aplikacja jest zbyt duża, wielu użytkowników dwa razy się zastanawia, zanim kliknie przycisk instalacji, a co gorsza, rezygnuje z pobierania w połowie. Co więcej, duża aplikacja zajmuje więcej miejsca w telefonie i może ostatecznie wpłynąć na szybkość reakcji systemu.
Aby zapobiec przekształceniu się Twojego projektu w cyfrowy gigant, istnieje kilka strategii, od czyszczenia kodu po optymalizację obrazu. W tym artykule zagłębimy się w wykorzystanie narzędzi takich jak R8 i ProGuard , a także w magię pakietów aplikacji, aby Twoja aplikacja była jak najlżejsza i najszybsza, zapewniając jej bezbłędne działanie nawet na urządzeniach o niższej wydajności.
Zrozumienie, co naprawdę jest ważne w Twojej aplikacji
Zanim zaczniemy, musimy wiedzieć, gdzie znajduje się większość danych. Rozmiar aplikacji zazwyczaj dzieli się na cztery główne bloki. Po pierwsze, mamy kod bajtowy Java lub Kotlin i jego biblioteki, które zazwyczaj stanowią od 30% do 40%. Następnie mamy zasoby, takie jak układy i animacje , o podobnej wielkości. Mamy również biblioteki natywne (C/C++) skompilowane dla różnych architektur (15–25%) i wreszcie zasoby lub pliki RAW (5–15%).
Aby uniknąć zgadywania, najlepiej skorzystać z narzędzia APK Analyzer w Android Studio (wybierając kolejno Kompilacja > Analiza APK). To narzędzie pozwala dokładnie sprawdzić, ile ważą klasy DEX, folder zasobów i biblioteki natywne, umożliwiając porównanie obecnych wersji z poprzednimi i ustalenie, które zmiany spowodowały wzrost rozmiaru pliku. Aby zgłębić ten temat, warto zrozumieć hierarchię plików w systemie Android i sposób ich organizacji.
Oczyszczanie kodu: Przejście z ProGuard do R8
Redukcja kodu jest niewątpliwie najskuteczniejszym sposobem na zmniejszenie liczby bajtów. Właśnie tutaj pojawia się ProGuard i jego współczesny następca, R8. ProGuard przez lata był standardem, dbając o usuwanie nieużywanych klas, pól i metod , optymalizując kod bajtowy i zaciemniając nazwy, aby były krótsze (i trudniejsze do odczytania dla każdego, kto próbuje zhakować kod).
Obecnie R8 jest domyślnym kompilatorem i wykonuje wszystko, co robił ProGuard, ale znacznie lepiej i szybciej. R8 implementuje bardziej agresywne wytrząsanie drzewa (tree shake) , łączy klasy z podobnymi funkcjami i optymalizuje wyliczenia, konwertując je na liczby całkowite. Ponadto umożliwia desugowanie, aby korzystać z nowoczesnych funkcji Javy 8 w starszych wersjach Androida.
Konfiguracja techniczna w build.gradle
Aby aktywować te optymalizacje w wersji wydania, należy skonfigurować plik kompilacji, ustawiając minifyEnabled jako prawda i łączenie plików reguł. Konieczne jest użycie proguard-android-optimize.txt aby w pełni wykorzystać optymalizacje. Podstawowy przykład konfiguracji obejmowałby: utrzymywać klasy aplikacji lub te oznaczone @Keep aby zapobiec przypadkowemu usunięciu plików przez R8.
Zarządzanie regułami dla bibliotek zewnętrznych
Czasami R8 jest zbyt wydajny i usuwa kod używany w refleksji, powodując błędy takie jak: ClassNotFoundExceptionDlatego księgarnie takie jak Retrofit, OkHttp lub Gson wymagają określonych zasad.Na przykład w przypadku Gsona kluczowe jest zachowanie nazw pól w modelach danych, aby deserializacja JSON nie zakończyła się niepowodzeniem. Jeśli po zaciemnieniu wystąpią błędy, plik mapowanie.txt To Twój najlepszy sojusznik przy tłumaczeniu śladów stosu i rozpoznawaniu miejsca wystąpienia błędu.
Inteligentna optymalizacja zasobów
Zasoby to często miejsca, w których marnuje się najwięcej miejsca. Prosta, ale skuteczna technika polega na aktywowaniu shrinkResources w pliku build.gradle. Usuwa to pliki, do których nie ma odniesienia w kodzie, choć ważne jest, aby wiedzieć, że jeśli dynamicznie wywołujesz zasób za pomocą getIdentifierBędziesz musiał to zadeklarować w pliku zachowaj.xml żeby nie zniknęło.
Obrazy i grafiki: mniej znaczy więcej
Format PNG zajmuje wiele niepotrzebnych megabajtów. Obecnie zaleca się migrację wszystkich danych do formatu WebP , który oferuje znacznie lepszą kompresję przy zachowaniu jakości. Konwersję można wykonać bezpośrednio w Android Studio, klikając obraz prawym przyciskiem myszy. W przypadku ikon i prostych kształtów idealnie sprawdzają się pliki Vector Drawables ; jeden plik XML zastępuje pięć wersji o różnej gęstości, co upraszcza konserwację i zmniejsza rozmiar pliku.
Ograniczanie liczby języków i gęstości
Wiele bibliotek zewnętrznych zawiera tłumaczenia na 50 języków, których Twoja aplikacja prawdopodobnie nie obsługuje. Aby to naprawić, użyj właściwości resConfigs w defaultConfigokreślając tylko języki, których faktycznie używasz (np. "es", "en"Podobnie możesz ograniczyć gęstość uwzględnionych ekranów, jeśli wiesz, że Twoja grupa docelowa korzysta z nowoczesnych urządzeń, usuwając zasoby ldpi lub mdpi z którego już nikt nie korzysta.
Zaawansowane strategie dystrybucji
Jeśli chcesz zdecydowanie zmniejszyć rozmiar pliku APK, powinieneś zrezygnować z uniwersalnych plików APK i przejść na pakiety aplikacji Android (.aab) . Zamiast wysyłać jeden ogromny plik ze wszystkim, co możliwe, Google Play generuje zoptymalizowany plik APK dla każdego urządzenia. W ten sposób użytkownik z telefonem ARM64 i ekranem xxhdpi pobiera tylko to, czego potrzebuje jego sprzęt , zmniejszając rozmiar pobieranego pliku nawet o 40%.
Dynamiczne moduły funkcyjne i aplikacje błyskawiczne
Nie cały kod musi być dostępny od samego początku. Dzięki modułom funkcji dynamicznych (Dynamic Feature Modules ) możesz oddzielić części aplikacji (takie jak zaawansowany edytor zdjęć czy tryb offline), aby były pobierane tylko wtedy, gdy użytkownik korzysta z tej funkcji. Z drugiej strony, aplikacje błyskawiczne (Instant Apps) pozwalają użytkownikom wypróbować aplikację bez jej instalowania, pobierając niezwykle lekki moduł bazowy za pośrednictwem adresu URL lub przycisku Google Play.
Audyt zależności i ostatecznych szczegółów
Czasami problemem nie jest kod, ale to, co pobierasz z zewnątrz. Biblioteki takie jak Guava czy Jackson mogą być bardzo duże; rozważ zastąpienie ich lżejszymi alternatywami, takimi jak kotlinx.serialization lub Gson . Zaleca się również korzystanie z czcionek do pobrania z Google Fonts zamiast dołączania dużych plików TTF do zasobów, co może zaoszczędzić kilka megabajtów, jeśli używasz wielu wariantów danej czcionki.
Aby zakończyć cykl optymalizacji, pamiętaj, że Android Go to rozwijający się rynek. Jeśli chcesz, aby Twoja aplikacja działała doskonale na urządzeniach z pamięcią RAM mniejszą niż 1 GB, staraj się, aby jej rozmiar nie przekraczał 40 MB. Korzystanie z narzędzia Android Lint do wykrywania osieroconych zasobów i utrzymywanie spójnej procedury czyszczenia sprawi, że Twoja aplikacja będzie wydajna, szybko się zainstaluje i zapewni płynne działanie, niezależnie od mocy urządzenia.