Pengembangan iteratif yang cepat untuk Android
Halaman ini menjelaskan cara bazel mobile-install
membuat pengembangan iteratif untuk Android menjadi jauh lebih cepat. Bagian ini menjelaskan manfaat pendekatan ini dibandingkan dengan kekurangan langkah-langkah pembuatan dan penginstalan terpisah.
Ringkasan
Untuk menginstal perubahan kecil pada aplikasi Android dengan sangat cepat, lakukan hal berikut:
- Temukan aturan
android_binary
aplikasi yang ingin Anda instal. - Hubungkan perangkat Anda ke
adb
. - Jalankan
bazel mobile-install :your_target
. Peluncuran aplikasi akan sedikit lebih lambat dari biasanya. - Edit kode atau resource Android.
- Jalankan
bazel mobile-install :your_target
. - Nikmati penginstalan inkremental yang cepat dan minimal.
Beberapa opsi command line untuk Bazel yang mungkin berguna:
--adb
memberi tahu Bazel biner adb mana yang akan digunakan--adb_arg
dapat digunakan untuk menambahkan argumen tambahan ke command lineadb
. Salah satu aplikasi yang berguna dari hal ini adalah memilih perangkat yang ingin Anda instal jika Anda memiliki beberapa perangkat yang terhubung ke workstation Anda:bazel mobile-install :your_target -- --adb_arg=-s --adb_arg=<SERIAL>
Jika ragu, lihat contoh, hubungi kami di Grup Google, atau laporkan masalah GitHub
Pengantar
Salah satu atribut terpenting dari toolchain developer adalah kecepatan: ada perbedaan besar antara mengubah kode dan melihatnya berjalan dalam waktu satu detik dan harus menunggu beberapa menit, terkadang berjam-jam, sebelum Anda mendapatkan masukan tentang apakah perubahan Anda melakukan apa yang Anda harapkan.
Sayangnya, toolchain Android tradisional untuk membangun .apk memerlukan banyak langkah monolitik dan berurutan, dan semua langkah ini harus dilakukan untuk membangun aplikasi Android. Di Google, menunggu lima menit untuk membangun perubahan satu baris bukanlah hal yang aneh dalam project yang lebih besar seperti Google Maps.
bazel mobile-install
membuat pengembangan iteratif untuk Android menjadi jauh lebih cepat dengan
menggunakan kombinasi penghapusan perubahan, pembagian tugas, dan manipulasi cerdas
internal Android, semuanya tanpa mengubah kode aplikasi Anda.
Masalah pada penginstalan aplikasi tradisional
Membangun aplikasi Android memiliki beberapa masalah, termasuk:
Dexing. Secara default, alat Dexer (dahulu
dx
, sekarangd8
ataur8
) dipanggil tepat satu kali dalam build dan tidak tahu cara menggunakan kembali tugas dari build sebelumnya: alat ini mengonversi setiap metode lagi, meskipun hanya satu metode yang diubah.Mengupload data ke perangkat. ADB tidak menggunakan bandwidth penuh koneksi USB 2.0, dan aplikasi yang lebih besar dapat memerlukan waktu yang lama untuk diupload. Seluruh aplikasi diupload, meskipun hanya sebagian kecil yang berubah, misalnya, resource atau satu metode, sehingga hal ini dapat menjadi hambatan besar.
Kompilasi ke kode native. Android L memperkenalkan ART, runtime Android baru, yang mengompilasi aplikasi ahead-of-time, bukan mengompilasinya just-in-time seperti Dalvik. Hal ini membuat aplikasi jauh lebih cepat dengan biaya waktu penginstalan yang lebih lama. Hal ini merupakan kompromi yang baik bagi pengguna karena mereka biasanya menginstal aplikasi sekali dan menggunakannya berkali-kali, tetapi menghasilkan pengembangan yang lebih lambat jika aplikasi diinstal berkali-kali dan setiap versi dijalankan paling banyak beberapa kali.
Pendekatan bazel mobile-install
bazel mobile-install
melakukan peningkatan berikut:
Desugaring dan dexing yang di-shard. Setelah mem-build kode Java aplikasi, Bazel akan membagi file class menjadi beberapa bagian yang ukurannya hampir sama dan memanggil
d8
secara terpisah pada setiap bagian tersebut.d8
tidak dipanggil pada shard yang tidak berubah sejak build terakhir. Shard ini kemudian dikompilasi menjadi APK ber-shard terpisah.Transfer file inkremental. Resource Android, file .dex, dan library native dihapus dari .apk utama dan disimpan di direktori penginstalan seluler terpisah. Hal ini memungkinkan Anda mengupdate kode dan resource Android secara terpisah tanpa menginstal ulang seluruh aplikasi. Dengan demikian, transfer file membutuhkan waktu lebih sedikit dan hanya file .dex yang telah berubah yang dikompilasi ulang di perangkat.
Penginstalan yang di-shard. Penginstalan seluler menggunakan alat
apkdeployer
Android Studio untuk menggabungkan APK yang di-shard di perangkat yang terhubung dan memberikan pengalaman yang kohesif.
Dexing dengan Sharding
Pengindeksan DEX yang di-shard cukup mudah: setelah file .jar dibuat, alat
akan membagi file tersebut menjadi file .jar terpisah dengan ukuran yang hampir sama, lalu memanggil
d8
pada file yang diubah sejak build sebelumnya. Logika yang menentukan shard mana yang akan di-dex tidak khusus untuk Android: logika ini hanya menggunakan algoritma penghapusan perubahan umum Bazel.
Versi pertama algoritma sharding hanya mengurutkan file .class secara alfabetis, lalu membagi daftar menjadi beberapa bagian berukuran sama, tetapi hal ini terbukti kurang optimal: jika suatu class ditambahkan atau dihapus (bahkan yang bertingkat atau anonim), semua class setelahnya secara alfabetis akan bergeser satu, sehingga menyebabkan sharding tersebut di-dex lagi. Oleh karena itu, diputuskan untuk membagi paket Java, bukan class individual. Tentu saja, hal ini masih menghasilkan pengindeksan banyak shard jika paket baru ditambahkan atau dihapus, tetapi hal itu jauh lebih jarang terjadi daripada menambahkan atau menghapus satu class.
Jumlah shard dikontrol oleh konfigurasi command line, menggunakan
flag --define=num_dex_shards=N
. Dalam kondisi ideal, Bazel akan
menentukan secara otomatis jumlah shard yang paling baik, tetapi saat ini Bazel harus mengetahui
kumpulan tindakan (misalnya, perintah yang akan dieksekusi selama build) sebelum
mengeksekusi salah satunya, sehingga tidak dapat menentukan jumlah shard yang optimal
karena tidak mengetahui jumlah class Java yang akan ada di
aplikasi. Secara umum, semakin banyak shard, semakin cepat build dan
penginstalan, tetapi semakin lambat startup aplikasi, karena linker
dinamis harus melakukan lebih banyak pekerjaan. Titik idealnya biasanya antara 10 dan 50 shard.
Deployment inkremental
Transfer dan penginstalan shard APK inkremental kini ditangani oleh utilitas
apkdeployer
yang dijelaskan dalam "Pendekatan penginstalan seluler".
Sedangkan versi penginstalan seluler (natif) sebelumnya memerlukan pelacakan manual
penginstalan pertama dan menerapkan tanda --incremental
secara selektif pada penginstalan berikutnya, versi terbaru di rules_android
telah sangat disederhanakan. Pemanggilan penginstalan seluler yang sama dapat digunakan terlepas dari berapa kali aplikasi telah diinstal atau diinstal ulang.
Secara umum, alat apkdeployer
adalah wrapper di sekitar berbagai sub-perintah adb
. Logika titik entri utama dapat ditemukan di class
com.android.tools.deployer.Deployer
, dengan class utilitas lain yang ditempatkan bersama dalam paket yang sama.
Class Deployer
menggunakan, antara lain, daftar jalur untuk memisahkan APK dan protobuf dengan informasi tentang penginstalan, serta memanfaatkan fitur deployment untuk Android App Bundle
guna membuat sesi penginstalan dan men-deploy pemisahan aplikasi secara inkremental.
Lihat class ApkPreInstaller
dan ApkInstaller
untuk mengetahui detail penerapan.
Hasil
Performa
Secara umum, bazel mobile-install
menghasilkan peningkatan kecepatan 4x hingga 10x dalam membangun dan menginstal aplikasi besar setelah perubahan kecil.
Angka berikut dihitung untuk beberapa produk Google:
Tentu saja, hal ini bergantung pada sifat perubahannya: kompilasi ulang setelah mengubah library dasar memerlukan waktu lebih lama.
Batasan
Trik yang dimainkan aplikasi stub tidak berfungsi dalam setiap kasus. Kasus berikut menunjukkan saat fitur ini tidak berfungsi seperti yang diharapkan:
Penginstalan seluler hanya didukung melalui aturan Starlark
rules_android
. Lihat "sejarah singkat penginstalan seluler" untuk mengetahui detail selengkapnya.Hanya perangkat yang menjalankan ART yang didukung. Penginstalan seluler menggunakan fitur API dan runtime yang hanya ada di perangkat yang menjalankan ART, bukan Dalvik. Runtime Android yang lebih baru dari Android L (API 21+) harus kompatibel.
Bazel itu sendiri harus dijalankan dengan versi bahasa dan runtime Java alat 17 atau yang lebih tinggi.
Versi Bazel sebelum 8.4.0 harus menentukan beberapa flag tambahan untuk mobile-install. Lihat tutorial Android Bazel. Flag ini memberi tahu Bazel lokasi aspek penginstalan seluler Starlark dan aturan yang didukung.
Sejarah singkat penginstalan seluler
Versi Bazel sebelumnya secara native menyertakan aturan build dan pengujian bawaan untuk bahasa dan ekosistem populer seperti C++, Java, dan Android. Oleh karena itu, aturan ini disebut sebagai aturan native. Bazel 8 (dirilis pada tahun 2024) menghapus dukungan untuk aturan ini karena banyak di antaranya telah dimigrasikan ke bahasa Starlark. Lihat "postingan blog Bazel 8.0 LTS" untuk mengetahui detail selengkapnya.
Aturan Android native lama juga mendukung versi native lama dari fungsi penginstalan seluler. Hal ini sekarang disebut sebagai "penginstalan seluler v1" atau "penginstalan seluler native". Fungsi ini dihapus di Bazel 8, bersama dengan aturan Android bawaan.
Sekarang, semua fungsi penginstalan seluler, serta semua aturan build dan pengujian Android, diimplementasikan di Starlark dan berada di repositori GitHub rules_android
. Versi terbaru dikenal sebagai "penginstalan seluler v3" atau "MIv3".
Catatan penamaan: Ada "mobile-install v2" yang hanya tersedia secara internal di Google pada satu waktu, tetapi ini tidak pernah dipublikasikan secara eksternal, dan hanya v3 yang terus digunakan untuk deployment rules_android internal Google dan OSS.