bazel mobil yükleme

Sorun bildir Kaynağı görüntüle Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Android için hızlı yinelemeli geliştirme

Bu sayfada, bazel mobile-install'nın Android'de yinelemeli geliştirmeyi nasıl çok daha hızlı hale getirdiği açıklanmaktadır. Bu yaklaşımın avantajları ile geleneksel uygulama yükleme yönteminin zorlukları açıklanmaktadır.

Özet

Android uygulamasında küçük değişiklikleri çok hızlı bir şekilde yüklemek için aşağıdakileri yapın:

  1. Yüklemek istediğiniz uygulamanın android_binary kuralını bulun.
  2. proguard_specs özelliğini kaldırarak Proguard'ı devre dışı bırakın.
  3. multidex özelliğini native olarak ayarlayın.
  4. dex_shards özelliğini 10 olarak ayarlayın.
  5. ART (Dalvik değil) çalıştıran cihazınızı USB üzerinden bağlayın ve cihazda USB hata ayıklamayı etkinleştirin.
  6. Koşu bazel mobile-install :your_target. Uygulama başlatma işlemi normalden biraz daha yavaş olacaktır.
  7. Kodu veya Android kaynaklarını düzenleyin.
  8. Koşu bazel mobile-install --incremental :your_target.
  9. Çok fazla beklemek zorunda kalmazsınız.

Bazel'e iletilebilecek ve işinize yarayabilecek bazı komut satırı seçenekleri:

  • --adb, Bazel'a hangi adb ikili dosyasının kullanılacağını bildirir.
  • --adb_arg, adb komut satırına ek bağımsız değişkenler eklemek için kullanılabilir. Bu özelliğin faydalı bir uygulaması, iş istasyonunuza bağlı birden fazla 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 uygulamayı otomatik olarak başlatır

Emin olmadığınız durumlarda örneğe bakın veya bize ulaşın.

Giriş

Geliştiricinin araç zincirinin en önemli özelliklerinden biri hızdır: Kodu değiştirip bir saniye içinde çalışırken görmek ile değişikliklerinizin beklentilerinizi karşılayıp karşılamadığına dair geri bildirim almadan önce dakikalarca, hatta bazen saatlerce beklemeniz arasında çok büyük bir fark vardır.

Maalesef .apk oluşturmak için geleneksel Android araç zinciri, birçok monolitik ve sıralı adım içerir. Android uygulaması oluşturmak için bu adımların tamamının uygulanması gerekir. Google'da, Google Haritalar gibi daha büyük projelerde tek satırlık bir değişikliği oluşturmak için beş dakika beklemek alışılmadık bir durum değildi.

bazel mobile-install, değişiklikleri budama, işi parçalama ve Android'in iç yapısını akıllıca değiştirme yöntemlerini kullanarak Android'de yinelemeli geliştirmeyi çok daha hızlı hale getirir. Tüm bunları, uygulamanızın kodunda herhangi bir değişiklik yapmadan gerçekleştirir.

Geleneksel uygulama yükleme ile ilgili sorunlar

Android uygulaması oluşturmayla ilgili bazı sorunlar vardır. Örneğin:

  • Dexing. Varsayılan olarak, "dx" derlemede tam olarak bir kez çağrılır ve önceki derlemelerdeki çalışmayı nasıl yeniden kullanacağını bilmez: Yalnızca bir yöntem değiştirilmiş olsa bile her yöntemi tekrar dex'ler.

  • 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 uzun zaman alabilir. Yalnızca küçük bölümler değişmiş olsa bile (ör. bir kaynak veya tek bir yöntem) uygulamanın tamamı yüklendiğinden bu durum büyük bir performans sorununa yol açabilir.

  • Yerel koda derleme. Android L, uygulamaları Dalvik gibi tam zamanında derlemek yerine önceden derleyen yeni bir Android çalışma zamanı olan ART'yi tanıttı. Bu, uygulamaların çok daha hızlı çalışmasını sağlar ancak yükleme süresini uzatır. Kullanıcılar genellikle bir uygulamayı bir kez yükleyip birçok kez kullandığı için bu durum kullanıcılar açısından iyi bir denge noktasıdır. Ancak bir uygulamanın birçok kez yüklendiği ve her sürümün en fazla birkaç kez çalıştırıldığı durumlarda geliştirme süreci yavaşlar.

bazel mobile-install yaklaşımı

bazel mobile-install aşağıdaki iyileştirmeleri yapar:

  • Parçalı dexing. Bazel, uygulamanın Java kodunu oluşturduktan sonra sınıf dosyalarını yaklaşık olarak eşit boyutlu parçalara ayırır ve her birinde dx'ı ayrı ayrı çağırır. dx, son derlemeden bu yana değişmeyen parçalarda çağrılmaz.

  • Artımlı dosya aktarımı. Android kaynakları, .dex dosyaları ve yerel kitaplıklar ana .apk'dan kaldırılır ve ayrı bir mobil yükleme dizininde saklanır. Bu sayede, kod ve Android kaynakları, uygulamanın tamamı yeniden yüklenmeden bağımsız olarak güncellenebilir. Böylece, dosyaların aktarılması daha az zaman alır ve yalnızca değişen .dex dosyaları cihazda yeniden derlenir.

  • Uygulamanın bazı bölümlerinin .apk dışından yüklenmesi. .apk dosyasına, cihazdaki mobil yükleme dizininden Android kaynaklarını, Java kodunu ve yerel kodu yükleyen, ardından kontrolü gerçek uygulamaya aktaran küçük bir saplama uygulaması yerleştirilir. Bu işlem, aşağıda açıklanan birkaç istisna dışında uygulama için tamamen şeffaftır.

Parçalı Dexing

Parçalanmış dexing oldukça basittir: .jar dosyaları oluşturulduktan sonra bir araç bunları yaklaşık olarak eşit boyuttaki ayrı .jar dosyalarına böler ve ardından önceki derlemeden bu yana değiştirilenler üzerinde dx'ı çağırır. Hangi parçaların dex'e dönüştürüleceğini belirleyen mantık Android'e özgü değildir. Yalnızca Bazel'in genel değişiklik temizleme algoritmasını kullanır.

Parçalama algoritmasının ilk sürümü, .class dosyalarını alfabetik olarak sıralayıp listeyi eşit boyutlu parçalara bölüyordu. Ancak bu yaklaşımın ideal olmadığı anlaşıldı: Bir sınıf eklendiğinde veya kaldırıldığında (iç içe yerleştirilmiş ya da anonim bir sınıf olsa bile) alfabetik olarak sonraki tüm sınıflar bir sıra kayıyor ve bu da parçaların yeniden dexlenmesine neden oluyordu. Bu nedenle, ayrı sınıflar yerine Java paketlerinin parçalanmasına karar verildi. Elbette bu durumda yeni bir paket eklenir veya kaldırılırsa yine birçok parça dizine eklenir ancak bu durum, tek bir sınıfın eklenmesi veya kaldırılmasına kıyasla çok daha az görülür.

Parça sayısı, BUILD dosyası tarafından kontrol edilir (android_binary.dex_shards özelliği kullanılarak). İdeal bir dünyada Bazel, kaç parçanın en iyi olacağını otomatik olarak belirlerdi. Ancak Bazel şu anda herhangi birini yürütmeden önce işlem kümesini (örneğin, derleme sırasında yürütülecek komutlar) bilmelidir. Bu nedenle, uygulamada sonunda kaç Java sınıfı olacağını bilmediği için optimum parça sayısını belirleyemez. Genel olarak, parça sayısı ne kadar fazla olursa derleme ve yükleme o kadar hızlı olur ancak dinamik bağlayıcı daha fazla iş yapmak zorunda kalacağından uygulama başlatma işlemi yavaşlar. İdeal nokta genellikle 10 ile 50 parça arasındadı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 aşağıdaki adımlardan oluşur:

  1. .apk dosyasını yükleme (genellikle adb install kullanılarak)
  2. .dex dosyalarını, Android kaynaklarını ve yerel kitaplıkları mobile-install dizinine yükleme

İlk adımda çok fazla artış olmaz: Uygulama ya yüklenir ya da yüklenmez. Bazel, her durumda gerekli olup olmadığını belirleyemediği için şu anda kullanıcının --incremental komut satırı seçeneğiyle bu adımı atması gerekip gerekmediğini belirtmesine bağlıdır.

İkinci adımda, derlemedeki uygulama dosyaları, cihazda hangi uygulama dosyalarının bulunduğu ve bu dosyaların sağlama toplamlarını listeleyen cihazdaki bir manifest dosyasıyla karşılaştırılır. Yeni dosyalar cihaza yüklenir, değiştirilmiş dosyalar güncellenir ve kaldırılmış dosyalar cihazdan silinir. Manifest yoksa her dosyanın yüklenmesi gerektiği varsayılır.

Cihazdaki bir dosyayı değiştirerek ancak manifestteki sağlama toplamını değiştirmeyerek artımlı yükleme algoritmasını yanıltmanın mümkün olduğunu unutmayın. Bu durum, cihazdaki dosyaların sağlama toplamı hesaplanarak önlenebilirdi ancak bu çözüm, yükleme süresindeki artışa değmeyecek bir çözüm olarak değerlendirildi.

Stub uygulaması

Stub uygulaması, cihazdaki mobile-install dizininden dex'lerin, yerel kodun ve Android kaynaklarının yüklenmesi için gereken işlemleri yapar.

Gerçek yükleme, BaseDexClassLoader alt sınıfı oluşturularak uygulanır ve makul ölçüde iyi belgelenmiş bir tekniktir. Bu işlem, uygulamanın sınıflarından herhangi biri yüklenmeden önce gerçekleşir. Böylece APK'daki tüm uygulama sınıfları, cihazdaki mobile-install dizinine yerleştirilerek adb install olmadan güncellenebilir.

Bu işlemin, uygulamanın sınıflarından herhangi biri yüklenmeden önce yapılması gerekir. Böylece, .apk dosyasında herhangi bir uygulama sınıfı bulunmaz. Bu da söz konusu sınıflarda yapılan değişikliklerin tam bir yeniden yükleme gerektireceği anlamına gelir.

Bu işlem, Application içinde belirtilen AndroidManifest.xml sınıfının stub uygulamasıyla değiştirilmesiyle gerçekleştirilir. Bu, uygulama başlatıldığında kontrolü ele alır ve Android çerçevesinin iç kısımlarında Java yansıtması kullanarak sınıf yükleyiciyi ve kaynak yöneticisini en erken anda (yapıcısı) uygun şekilde ayarlar.

İstemci uygulamasının yaptığı bir diğer işlem de mobil yükleme ile yüklenen yerel kitaplıkları başka bir konuma kopyalamaktır. Bu, dinamik bağlayıcının dosyalarda X bitinin ayarlanmasını gerektirdiği için zorunludur. Bu işlem, root olmayan bir adb tarafından erişilebilen hiçbir konumda yapılamaz.

Tüm bu işlemler tamamlandıktan sonra saplama uygulaması, gerçek Application sınıfını oluşturur ve kendisine yapılan tüm referansları Android çerçevesindeki gerçek uygulamayla değiştirir.

Sonuçlar

Performans

Genel olarak, bazel mobile-install, küçük bir değişiklikten sonra büyük uygulamaların oluşturulması ve yüklenmesinde 4 ila 10 kat hızlanma sağlar.

Aşağıdaki sayılar, birkaç Google ürünü için hesaplanmıştır:

Bu süre, değişikliğin niteliğine bağlıdır. Örneğin, temel bir kitaplık değiştirildikten sonra yeniden derleme daha uzun sürer.

Sınırlamalar

Sahte uygulamanın oynadığı oyunlar her durumda işe yaramaz. Aşağıdaki durumlarda bant genişliği beklendiği gibi çalışmaz:

  • Context, ContentProvider#onCreate() uygulamasında Application sınıfına yayınlandığında Bu yöntem, uygulama başlatılırken Application sınıfının örneğini değiştirmeden önce çağrılır. Bu nedenle, ContentProvider gerçek uygulama yerine hâlâ sahte uygulamaya referans verir. Bu, Context öğesini bu şekilde yayınlamanız gerekmediğinden bir hata olarak değerlendirilmeyebilir ancak Google'daki birkaç uygulamada bu durumun yaşandığı görülmektedir.

  • bazel mobile-install tarafından yüklenen kaynaklar yalnızca uygulama içinden kullanılabilir. Kaynaklara PackageManager#getApplicationResources() aracılığıyla diğer uygulamalar tarafından erişilirse bu kaynaklar, son artımlı olmayan yüklemeden alınır.

  • ART'nin çalıştırılmadığı cihazlar. Stub uygulaması Froyo ve sonraki sürümlerde iyi çalışsa da Dalvik'te, kodunun belirli durumlarda (ör. Java ek açıklamaları belirli bir şekilde kullanıldığında) birden fazla .dex dosyasına dağıtılması halinde uygulamanın yanlış olduğunu düşünmesine neden olan bir hata vardır. Uygulamanız bu hataları tetiklemediği sürece Dalvik ile de çalışır (ancak eski Android sürümlerine yönelik desteğin önceliğimiz olmadığını unutmayın).