Android için hızlı yinelemeli geliştirme
Bu sayfada bazel mobile-install
ürününün Android için yinelemeli geliştirmeyi nasıl çok daha hızlı hale getirdiği açıklanmaktadır. Makalede bu yaklaşımın avantajları, geleneksel uygulama yükleme yönteminin zorluklarına kıyasla açıklanmıştır.
Özet
Bir Android uygulamasındaki küçük değişiklikleri çok hızlı bir şekilde yüklemek için aşağıdakileri yapın:
- Yüklemek istediğiniz uygulamanın
android_binary
kuralını bulun. proguard_specs
özelliğini kaldırarak ProGuard'ı devre dışı bırakın.multidex
özelliğininative
olarak ayarlayın.dex_shards
özelliğini10
olarak ayarlayın.- ART (Dalvik değil) çalıştıran cihazınızı USB üzerinden bağlayın ve cihazda USB hata ayıklama özelliğini etkinleştirin.
bazel mobile-install :your_target
komutunu çalıştırın. Uygulama normalden biraz daha daha yavaş başlatılır.- Kodu veya Android kaynaklarını düzenleyin.
bazel mobile-install --incremental :your_target
komutunu çalıştırın.- Çok fazla beklemek zorunda kalmamanın keyfini çıkarın.
Bazel için yararlı olabilecek bazı komut satırı seçenekleri:
--adb
, Bazel'a hangi adb ikili programının kullanılacağını söyler--adb_arg
,adb
öğesinin komut satırına fazladan bağımsız değişkenler eklemek için kullanılabilir. Bunun yararlı bir uygulaması, iş istasyonunuza bağlı birden çok cihazınız varsa hangi cihaza yüklemek istediğinizi seçmektir:bazel mobile-install --adb_arg=-s --adb_arg=<SERIAL> :your_target
--start_app
uygulaması otomatik olarak başlatır
Emin olamadığınız durumlarda örneği inceleyin veya bizimle iletişime geçin.
Giriş
Bir geliştiricinin araç zincirinin en önemli özelliklerinden biri hızdır. Kodu değiştirmek ile kodun bir saniye içinde çalıştığını görmek ve değişikliklerinizin beklediğiniz gibi yapıp yapmadığıyla ilgili geri bildirim almadan önce dakikalar, bazen saatlerce beklemek zorunda kalmak arasında çok büyük bir fark vardır.
Ne yazık ki .apk oluşturmak için kullanılan geleneksel Android araç zinciri, pek çok monolitik, ardışık adım gerektirir ve bunların bir Android uygulaması geliştirmek için bunların hepsi yapılması gerekir. Google'da, tek satırlı bir değişiklik oluşturmak için beş dakika beklemek Google Haritalar gibi daha büyük projelerde olağan dışı bir durumdu.
bazel mobile-install
; değişiklik ayıklama, iş parçalama ve Android dahili bileşenlerinin zekice değiştirilmesini bir arada kullanarak, uygulamanızın kodunda hiçbir değişiklik yapmadan Android için yinelemeli geliştirmeyi çok daha hızlı hale getirir.
Geleneksel uygulama yüklemeyle ilgili sorunlar
Android uygulaması oluştururken aşağıdakiler de dahil olmak üzere bazı sorunlar vardır:
Dexing. Varsayılan olarak, "dx" derlemede tam olarak bir kez çağrılır ve önceki derlemelere ait çalışmanın nasıl yeniden kullanılacağını bilmez: Yalnızca bir yöntem değiştirilse bile her yöntemi tekrar dxştirir.
Cihaza veri yükleme. adb, USB 2.0 bağlantısının tam bant genişliğini kullanmaz ve daha büyük uygulamaların yüklenmesi çok zaman alabilir. Bir kaynak veya tek bir yöntem gibi yalnızca küçük parçalar değişmiş olsa bile uygulamanın tamamı yüklenir. Dolayısıyla bu, büyük bir performans sorunu olabilir.
Yerel koda derleme. Android L, uygulamaları Dalvik gibi tam zamanında derlemek yerine önceden derleyen yeni Android çalışma zamanı olan ART'ı kullanıma sundu. Bu da uygulamaları, daha uzun yükleme sürelerine mal olacak şekilde çok daha hızlı hale getirir. Bu, bir uygulamayı genellikle bir kez yükleyip birçok kez kullandıkları, ancak uygulamanın birçok kez yüklendiği ve her sürümün en az birkaç kez çalıştırıldığı daha yavaş bir gelişime neden olduğundan kullanıcılar için iyi bir dengedir.
bazel mobile-install
yaklaşımı
bazel mobile-install
aşağıdaki iyileştirmeleri yapar:
Parçalı dexing. Uygulamanın Java kodunu oluşturduktan sonra Bazel, sınıf dosyalarını yaklaşık olarak eşit boyutta parçalara ayırır ve bunlarda ayrı olarak
dx
yöntemini çağırır.dx
, son derlemeden bu yana değişmemiş parçalarda çağrılmaz.Artımlı dosya aktarımı. Android kaynakları, .dex dosyaları ve yerel kitaplıklar ana .apk'den kaldırılır ve ayrı bir mobil yükleme dizininde depolanır. Bu, uygulamanın tamamını yeniden yüklemeden kodu ve Android kaynaklarını bağımsız olarak güncellemeyi mümkün kılar. Böylece, dosyaların aktarılması daha kısa sürer ve yalnızca değiştirilen .dex dosyaları cihaz üzerinde yeniden derlenir.
Uygulamanın bazı kısımları .apk dışından yükleniyor. Cihaz üzerindeki mobil yükleme dizininden Android kaynaklarını, Java kodunu ve yerel kodu yükleyen, ardından kontrolü gerçek uygulamaya aktaran .apk'ye küçük bir saplama uygulaması yerleştirilir. Aşağıda açıklanan birkaç köşe durumu haricinde tüm bunlar uygulama tarafından şeffaf bir şekilde işlenir.
Parçalı Dexing
Parçalı dexing işlemi makul ölçüde basittir: .jar dosyaları derlendikten sonra, bir araç bu dosyaları yaklaşık olarak eşit boyutta ayrı .jar dosyaları halinde parçalara ayırır, ardından önceki derlemeden bu yana değiştirilen dosyalarda dx
çağırır. Hangi kırıkların ayıklanacağını belirleyen mantık Android'e özel değildir. Yalnızca Bazel'ın genel değişiklik ayıklama algoritması kullanılır.
Parçalama algoritmasının ilk sürümü, .class dosyalarını alfabetik olarak sıralıyor ve ardından listeyi eşit boyutlu parçalara ayırıyordu. Ancak bunun yetersiz olduğunu kanıtladı: Bir sınıf eklenir veya kaldırılırsa (iç içe veya anonim bir sınıf olsa bile) tüm sınıfların bir birim kaydırılmasından sonra alfabetik olarak bir değişim olur ve bu da söz konusu parçalara tekrar dağılmasıyla sonuçlanır. Bu nedenle, bağımsız sınıflar yerine Java paketlerini parçalamaya karar verildi. Elbette, yeni bir paket eklenirse veya kaldırılırsa bu yine de çok sayıda parçanın dizine eklenmesine neden olur, ancak bu, tek bir sınıf eklemek veya çıkarmaktan çok daha az sıklıkta gerçekleşir.
Parça sayısı, BUILD dosyası (android_binary.dex_shards
özelliği kullanılarak) tarafından kontrol edilir. İdeal bir dünyada Bazel kaç tane parçanın en iyi olduğunu otomatik olarak belirler. Ancak Bazel şu anda herhangi bir
işlemi yürütmeden önce işlem kümesini (örneğin, derleme
sırasında yürütülecek komutlar) bilmelidir.
Bu nedenle, uygulamada kaç Java sınıfı olacağını bilemez,
çünkü uygulamanın daha hızlı yüklenmesi ve daha yavaş uygulama parçaları olur. En iyi konum genellikle 10 ila 50 kırıktır.
Artımlı dosya aktarımı
Uygulamayı oluşturduktan sonraki adım, tercihen mümkün olan en az çabayla uygulamayı yüklemektir. Yükleme işlemi aşağıdaki adımlardan oluşur:
- .apk yükleniyor (genelde
adb install
kullanılıyor) - .dex dosyalarını, Android kaynaklarını ve yerel kitaplıkları mobile-install dizinine yükleyerek
İlk adımda fazla bir artımlılık yoktur: Uygulama ya yüklüdür ya da yüklenmemiştir. Bazel, gerekli olup olmadığını her durumda belirleyemeyeceğinden şu anda bu adımı --incremental
komut satırı seçeneği üzerinden yapıp yapmayacağını belirtmek için kullanıcıdan güveniyor.
İkinci adımda, uygulamanın derlemedeki dosyaları, cihazda hangi uygulama dosyalarının bulunduğunu ve sağlamalarının listelendiği cihaz üzerindeki bir manifest dosyasıyla karşılaştırılır. Yeni dosyalar cihaza yüklenir, değiştirilen dosyalar güncellenir ve kaldırılan dosyalar cihazdan silinir. Manifest mevcut değilse her dosyanın yüklenmesi gerektiği varsayılır.
Cihazdaki bir dosyayı değiştirerek artımlı yükleme algoritmasını kandırabilirsiniz, ancak manifest dosyasında dosyanın sağlama toplamını değiştirmek mümkün değildir. Bu durum, cihazdaki dosyaların sağlaması hesaplanarak korunabilirdi, ancak yükleme süresindeki artışa değmeyeceğine karar verildi.
Saplama uygulaması
Saplama uygulamasında dex'leri, yerel kodu ve Android kaynaklarını cihaz üzerindeki mobile-install
dizininden yükleme işlemi gerçekleşir.
Gerçek yükleme, BaseDexClassLoader
alt sınıflandırması tarafından uygulanır ve yeterince iyi belgelenmiş bir tekniktir. Bu işlem, uygulamanın sınıflarından biri yüklenmeden önce gerçekleşir. Böylece apk'deki uygulama sınıfları, cihaz üzerindeki mobile-install
dizinine yerleştirilebilir ve böylece adb install
olmadan güncellenebilir.
Bu işlemin, uygulamanın sınıflarından herhangi biri yüklenmeden yapılması gerekir. Böylece .apk'de uygulama sınıfı bulunmasına gerek yoktur. Bu da söz konusu sınıflarda yapılan değişikliklerin tam yeniden yükleme gerektirdiği anlamına gelir.
Bu işlem, AndroidManifest.xml
politikasında belirtilen Application
sınıfının saplama uygulamasıyla değiştirilmesiyle gerçekleştirilir. Bu, uygulamanın başlatılmasını kontrol etme imkanı tanır ve Android çerçevesinin dahili bileşenlerinde Java yansımasını kullanarak en kısa sürede sınıf yükleyici ile kaynak yöneticisini (kurucusu) uygun şekilde düzenler.
Saplama uygulamasının yaptığı bir başka işlem de, mobil yükleme ile yüklenen yerel kitaplıkları başka bir konuma kopyalamaktır. Bu işlem, dinamik bağlayıcı için dosyalarda X
bitinin ayarlanması gerektiğinden gereklidir. Kök olmayan bir adb
tarafından erişilebilen hiçbir konumda bunu yapmak mümkün değildir.
Tüm bu işlemler tamamlandıktan sonra, saplama uygulaması gerçek Application
sınıfını somutlaştırarak Android çerçevesi içinde gerçek uygulamaya yapılan tüm referansları değiştirir.
Sonuçlar
Performans
bazel mobile-install
, genellikle küçük bir değişiklikten sonra büyük uygulamalar oluşturma ve yükleme hızını 4 ila 10 kat artırır.
Aşağıdaki sayılar birkaç Google ürünü için hesaplanmıştır:
Bu elbette değişikliğin yapısına bağlıdır: Bir temel kitaplığı değiştirdikten sonra yeniden derleme daha uzun sürer.
Sınırlamalar
Saplama uygulamasının yaptığı hileler her durumda işe yaramaz. Aşağıdaki örneklerde, beklendiği gibi çalışmadığı yerler vurgulanmaktadır:
Context
,ContentProvider#onCreate()
ile ilgiliApplication
sınıfına yayınlandığında. Bu yöntem,Application
sınıfı örneğini değiştirme fırsatımız olmadan uygulama başlatma sırasında çağrılır. Bu nedenleContentProvider
, gerçek uygulama yerine saplama uygulamasına referans vermeye devam eder. MuhtemelenContext
öğesini bu şekilde aşağı düşürmeniz gerekmediği için bu bir hata değildir, ancak bu durum Google'daki birkaç uygulamada yaşanmaktadır.bazel mobile-install
tarafından yüklenen kaynaklar yalnızca uygulama içinden kullanılabilir. Diğer uygulamalarPackageManager#getApplicationResources()
üzerinden kaynaklara erişiyorsa bu kaynaklar son ek olmayan yükleme işleminden alınır.ART kullanmayan cihazlar. Saplama uygulaması, Froyo ve sonraki sürümlerde sorunsuz bir şekilde çalışsa da Dalvik, bazı durumlarda (örneğin, Java ek açıklamaları belirli bir şekilde kullanıldığında) kodu birden fazla .dex dosyasına dağıtılmışsa uygulamanın hatalı olduğunu düşünür. Uygulamanız bu hataları gıdıklanmadığı sürece Dalvik ile de çalışmalıdır (ancak, eski Android sürümlerini desteklemenin tam olarak odak noktamız olmadığını unutmayın.)