
/ PxHere / PD
Mengoptimalkan bobot APK adalah tugas yang tidak sepele, tetapi sangat relevan pada zaman Aplikasi Instan. Mengaktifkan proguard akan menyelamatkan Anda dari kode yang tidak perlu jika dependensi Anda dapat ditentukan pada tahap kompilasi, tetapi ada beberapa jenis file lain di APK yang dapat dikecualikan dari perakitan.
Di bawah kucing tentang cara membuat dependensi - ditentukan pada tahap kompilasi, file mana yang dapat dikecualikan dari perakitan dan bagaimana melakukannya, serta, kami akan menganalisis cara mengecualikan komponen yang tidak digunakan dari perakitan jika Anda memiliki beberapa aplikasi dengan basis kode yang umum.
Sebelum membaca
- Sebelum menerapkan tips dari artikel, optimalkan APK untuk panduan Google . Artikel ini ditujukan bagi mereka yang tidak memiliki optimisasi standar yang cukup.
- Dengan "proguard" yang saya maksud adalah kompiler yang mengoptimalkan dengan minifikasi.
- Menurut komponen, maksud saya adalah fitur tertentu dari produk dari sudut pandang bisnis. Dalam kasus kami, ini hanya kumpulan file dalam paket tertentu. Kami memiliki satu modul gradle untuk seluruh aplikasi.
Berat APK yang dioptimalkan Google kami adalah 4.4
.
File ekstra
Mari kita mulai dengan yang sederhana. Jika Anda tidak menggunakan kotlin-reflect , maka Anda dapat mengecualikan meta-informasi tentang kelas kotlin dari majelis. Anda dapat melakukan ini sebagai berikut:
In build.gradle (Module: app)
android { packagingOptions { exclude("META-INF/*.kotlin_module") exclude("**.kotlin_builtins") exclude("**.kotlin_metadata") } }
Refleksi Java tidak memerlukan *.kotlin_module
, *.kotlin_builtins
dan *.kotlin_metadata
. Menentukan refleksi mana yang Anda gunakan sangat sederhana. Jika Anda menulis obj::class.<method>
, maka Anda menggunakan refleksi kotlin, jika obj::class.java.<method>
, maka java reflection.
Hasil optimasi untuk kami: -602.1 kb
Ketergantungan
Perpustakaan terkadang menambahkan dependensi untuk kasus-kasus yang tidak pernah terjadi dalam aplikasi Anda. Sebagai contoh, ktor-klien menarik kotlin-refleksi bersama dengannya (0,5 mb!).
Saya bergumul dengan kasus-kasus seperti berikut: Saya mengumpulkan APK dengan minifyEnabled = true
, melemparkannya ke dalam penganalisa Android Studio, mengunduh mapping.txt
dan mencari paket yang, secara teori, tidak boleh ada dalam perakitan. Misalnya, kotlin.reflect
. Setelah menjalankan ./gradlew app:dependencies
di folder proyek untuk mencari dependensi (jangan lupa untuk menambah panjang sejarah di terminal. Pohon dependensi bisa jadi besar!). Dari pohon ini mudah untuk memahami apa yang merujuk pada dependensi yang tidak perlu dan mengeluarkannya. Di build.gradle
modul Anda:
dependencies { implementation("io.ktor:ktor-client-core:$ktorVersion") { exclude(group: "org.jetbrains.kotlin", module: "kotlin-reflect") } implementation("io.ktor:ktor-client-okhttp:$ktorVersion") { exclude(group: "org.jetbrains.kotlin", module: "kotlin-reflect") } }
Kode ini menghilangkan ketergantungan perpustakaan ktor-klien pada kotlin-reflect . Jika Anda ingin mengecualikan sesuatu yang lain, gantikan nilainya.
!!! Gunakan saran ini dengan sangat hati-hati! Sebelum menghilangkan ketergantungan, pastikan Anda tidak membutuhkannya. Jika tidak, maka aplikasi mungkin mulai turun produksi !!!
Hasil optimasi untuk kami: -500,3 kb
Validasikan XML Anda
Sayangnya, proguard tidak menghapus file markup XML tambahan dari folder layout. XML yang tidak digunakan dapat menggunakan widget "berat" dan proguard tidak akan dapat mengecualikan mereka dari perakitan juga! Untuk menghindarinya, hapus sumber daya yang tidak digunakan dengan Refactor -> Remove unused resources...
Periksa di Anda
Jika Anda, seperti kami, menggunakan runtime DI, maka periksa apakah Anda memiliki penyedia untuk dependensi yang tidak Anda gunakan. Proguard tidak dapat mengecualikan mereka dari rakitan karena mereka tidak digunakan dari sudut pandang kompiler. Anda menggunakannya ketika membangun grafik ketergantungan.
Kecualikan Ketergantungan pada Debug dari Rilis Build
Alat debugging dapat mengambil banyak ruang secara tak terduga. Sebagai contoh, stetho
memiliki berat sekitar 0.2
setelah kompresi! Bagaimanapun, lebih baik untuk mengecualikan seluruh infrastruktur debugging dari rilis rilis sehingga tidak ada yang bisa belajar terlalu banyak tentang aplikasi Anda hanya dengan mengunduhnya dari Google Play.
Anda dapat membuat versi berbeda dari file yang sama untuk debug dan rilis. Untuk melakukan ini, di folder src
, di sebelah main
, buat folder debug
dan release
. Sekarang Anda dapat menulis fungsi initStetho
yang menginisialisasi Stetho di file src/debug/java/your/pkg/Stetho.kt
dan fungsi initStetho
yang tidak melakukan apa pun di file src/release/java/your/pkg/Stetho.kt
.
Untuk berjaga-jaga, pastikan bahwa ketergantungan ini disertakan hanya dalam build debug. Anda bisa melakukan ini dengan mengganti implementation
dengan debugImplementation
di build.gradle
. Lebih sering daripada tidak, proguard menghilangkan file yang tidak perlu bahkan tanpa langkah ini, tetapi tidak selalu. Jawaban untuk pertanyaan "mengapa?" di bawah ini dalam teks artikel .
Terkadang, pada basis kode yang sama, beberapa versi aplikasi yang berbeda dikeluarkan. Ini dapat berupa versi yang berbeda untuk negara atau wilayah yang berbeda, atau, seperti dalam kasus kami, untuk klien yang berbeda. Di bawah ini adalah tips tentang cara menurunkan platform.

/ PxHere / PD
Pengalaman kami
Kami sedang mengembangkan perancang aplikasi seluler E-SHOP . Kami memiliki beberapa lusin pelanggan dan masing-masing memiliki komponen sendiri-sendiri. Beberapa komponen digunakan oleh semua pelanggan, beberapa hanya sebagian. Tugas kita adalah untuk memasukkan dalam perakitan klien hanya komponen-komponen yang dia butuhkan.
Tandai Pengecualian
Untuk setiap klien kami membuat ProductFlavor terpisah. Ini nyaman karena mudah untuk membuat sumber daya yang berbeda untuk klien yang berbeda, IDE menyediakan antarmuka grafis untuk beralih antar rasa, dan cache berfungsi dengan baik. Dan Anda juga dapat membuat BuildConfig.java
Anda sendiri untuk setiap klien. Nilai-nilai bidang dari kelas ini diketahui pada tahap kompilasi. Inilah yang kami butuhkan! Buat bidang tipe boolean
untuk setiap komponen.
android { productFlavors { client1 { buildConfigField("boolean", "IS_CATALOG_ENABLED", "true") } client2 { buildConfigField("boolean", "IS_CATALOG_ENABLED", "false") } } }
Ini adalah versi konfigurasi yang disederhanakan. Hadiah ini rumit karena integrasi dengan CI kami.
Sekarang diketahui apakah komponen tersebut aktif pada tahap kompilasi, dan proguard dapat mengeluarkannya dari perakitan!
XML lagi
Sekarang masalah dengan tata letak XML yang tidak digunakan mengambil dimensi baru! Anda tidak bisa mengambil dan menghapus markup komponen hanya karena beberapa pelanggan tidak membutuhkannya.
Dalam aplikasi XML kami dari salah satu komponen yang jarang digunakan, kami menggunakan widget yang merujuk ke pustaka pengenalan gambar firebase.ml.vision
. Beratnya sekitar 0,2 mb, yang banyak. Diputuskan untuk menambahkan widget ini dengan kode alih-alih menyatakannya di markup. Setelah itu, proguard dapat mengecualikan vision
dari majelis untuk klien yang tidak membutuhkannya.
Hasil optimasi untuk kami: -222,3 kb untuk APK rata-rata
@Keep
Ada 2 cara untuk memberi tahu proguard bahwa kelas Anda tidak dapat dikecilkan: tulis aturan di file proguard-rules.pro
atau @Keep
penjelasan @Keep
. Di perpustakaan play-services-vision
, anotasi ini ada di kelas root. Oleh karena itu, 0,2 mb mati bahkan dalam aplikasi klien yang tidak memerlukan pengenalan gambar.
Saya tidak menemukan cara sederhana dan aman untuk menghapus anotasi ini. Jika Anda tahu caranya - silakan tulis di komentar.
Untungnya, pustaka firebase.ml.vision
, yang merupakan versi lebih baru dari play-services-vision
, tidak menggunakan anotasi ini dan kami memecahkan masalahnya dengan masuk ke sana.
Dan lagi DI
Terakhir tapi tidak kalah pentingnya. DI untuk komponen yang terputus. Semuanya sederhana di sini: untuk setiap komponen kami menggunakan wadah kami sendiri, dan kami menghubungkan dependensi umum melalui modul terpisah.
Hasil optimasi untuk kami: -20.1 kb untuk APK rata-rata
Kesimpulan
- Berat APK rata-rata telah menurun dari
4.4
menjadi 3.1
, dan minimum - menjadi 2.5
! - Kode aplikasi tidak dirugikan, tetapi ditingkatkan. DI sekarang lebih mudah untuk dikerjakan
Semua optimisasi yang disajikan dalam artikel adalah "buah-buahan yang mudah digantung." Mereka cukup mudah diimplementasikan dan dengan cepat mendapatkan hasilnya. Hingga -43% untuk APK yang sudah dioptimalkan dalam kasus kami. Saya harap saya menghemat waktu Anda dengan mendaftarkan semuanya di satu tempat.
Terima kasih semuanya!