64K'dan fazla yöntemler içeren uygulamalar için multidex'i etkinleştirin

Uygulamanızda API 20 veya daha düşük minSdk sürümü varsa ve kitaplığın başvuruda bulunduğu kitaplık 65.536 yöntemi aştığında, uygulamanızın Android derleme mimarisinin sınırına ulaştığını gösterir:

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

Derleme sisteminin daha eski sürümleri, aynı sorun:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

Bu hata koşullarında ortak bir sayı gösterilir: 65536. Bu numara kullanabileceğiniz toplam referans sayısını tek bir Dalvik Yürütülebilir (DEX) bayt kodu dosyasındaki kod tarafından çağrılır. Bu sayfada, paydaşlara iletmek için multidex adlı bir uygulama yapılandırmasını etkinleştirmenizi sağlar. kullanarak birden fazla DEX dosyası oluşturabilir ve okuyabilirsiniz.

64K referans sınırı hakkında

Android uygulaması (APK) dosyaları, Dalvik Yürütülebilir (DEX) dosyalar: Uygulamanızı çalıştırmak için kullanılan derlenmiş kodu içerir. Dalvik Yürütülebilir teknik özelliği, tek bir DEX dosyasında 65.536'ya (Android dahil olmak üzere) referans verilebilir. ve yöntemlerini kendi kodunuza da ekleyebilirsiniz.

bağlamındaki kilo veya K terimi, 1024 (veya 2^10). 65.536, 64x1024'e eşit olduğundan bu sınıra _64K referans sınırı_.

Android 5.0'dan önceki Multidex desteği

Platformun Android 5.0'dan (API düzeyi 21) önceki sürümlerinde Dalvik kullanılır çalışma zamanına bağlı olarak daha iyidir. Dalvik, uygulamaları varsayılan olarak tek bir APK başına classes.dex bayt kod dosyası. Bunu önlemek için sınırlı olması durumunda, multidex kitaplığını modül düzeyindeki build.gradle öğesine ekleyin veya build.gradle.kts dosya:

Eski

dependencies {
    def multidex_version = "2.0.1"
    implementation "androidx.multidex:multidex:$multidex_version"
}

Kotlin

dependencies {
    val multidex_version = "2.0.1"
    implementation("androidx.multidex:multidex:$multidex_version")
}

Bu kitaplık, uygulamanızın birincil DEX dosyasının bir parçası haline gelir ve ardından ek DEX dosyalarına ve içerdikleri koda erişimi yönetir. Bu kitaplığın mevcut sürümlerini görüntülemek için bkz. çokludex sürümleri.

Daha fazla bilgi için uygulamanızı multidex için yapılandırın.

Android 5.0 ve sonraki sürümler için Multidex desteği

Android 5.0 (API düzeyi 21) ve sonraki sürümlerde, APK dosyalarından birden fazla DEX dosyasının yüklenmesini yerel olarak destekler. SANATÇILAR uygulama yükleme anında önceden derleme yapar, classesN.dex dosya oluşturup bunları tek bir dosyada derliyor için OAT dosyası teknikler de vardır. Dolayısıyla, minSdkVersion 21 veya üzeri bir değerse multidex varsayılan olarak etkindir ve multidex kitaplığına ihtiyacınız yoktur.

Android 5.0 hakkında daha fazla bilgi için çalışma zamanı için Android Runtime (ART) ve Dalvik bilgilerini okuyun.

Not: Uygulamanızı Android Studio kullanarak çalıştırırken derleme, dağıtım yaptığınız hedef cihazlara göre optimize edilir. Buna, hedef cihazlar çalışırken multidex'in etkinleştirilmesi de dahildir. Android 5.0 ve sonraki sürümler. Bu optimizasyon yalnızca Android Studio için hâlâ sürüm derlemenizi yapılandırmanız gerekebilir 64K sınırını aşmamak için çokludex kullanın.

64K sınırından kaçının.

Uygulamanızı 64K veya daha fazla yöntem referansının kullanılmasını etkinleştirecek şekilde yapılandırmadan önce tarafından tanımlanan yöntemler de dahil olmak üzere uygulama kodunuz tarafından çağrılan toplam referans sayısını azaltmak için veya eklenmiş kitaplıklar olabilir.

Aşağıdaki stratejiler, DEX referans sınırına ulaşmaktan kaçınmanıza yardımcı olabilir:

Uygulamanızın doğrudan ve geçişli bağımlılıklarını inceleme
Uygulamanıza eklediğiniz büyük bir kitaplık bağımlılığının değerinin kod miktarından ağır olup olmadığını düşünün eklenip eklenmediğini kontrol edin. Sık karşılaşılan ancak sorunlu bir kalıp, çok büyük bir kitaplık eklemektir. çünkü birkaç yardımcı yöntemi faydalı oldu. Uygulama kodu bağımlılıklarını azaltmak çoğu zaman işe yarar DEX referans sınırından kaçınmış olursunuz.
Kullanılmayan kodları R8 ile kaldırın
R8'i çalıştırmak için kod küçültmeyi etkinleştirin oluşturmanız önerilir. Şunları yaptığınızdan emin olmak için küçültmeyi etkinleştirin: APK'larınızla kullanılmayan kod göndermiyor. Kod daraltma doğru yapılandırıldıysa kullanılmayan kod ve kaynakları da bağımlılıklarınızdan kaldırabilir.

Bu teknikleri kullanmak APK'nızın genel boyutunu küçültmenize ve uygulamanızda çokludex ihtiyacını ortadan kaldırın.

Uygulamanızı multidex için yapılandırma

Not: minSdkVersion değeriniz 21 veya daha yüksek bir değere ayarlanmışsa multidex varsayılan olarak etkinleştirilir. ve multidex kitaplığına ihtiyacınız yok.

minSdkVersion değeriniz 20 veya daha düşük bir değere ayarlanırsa şunu kullanmalıdır: multidex kitaplığı'na uygulama projenizde yapılan aşağıdaki değişiklikler:

  1. Modül düzeyindeki build.gradle dosyasını şu şekilde değiştirin: çokludex'i etkinleştirin ve çokludex kitaplığını aşağıda gösterildiği gibi bağımlılık olarak ekleyin:

    Eski

    android {
        defaultConfig {
            ...
            minSdkVersion 15 
            targetSdkVersion 33
            multiDexEnabled true
        }
        ...
    }
    
    dependencies {
        implementation "androidx.multidex:multidex:2.0.1"
    }
    

    Kotlin

    android {
        defaultConfig {
            ...
            minSdk = 15 
            targetSdk = 33
            multiDexEnabled = true
        }
        ...
    }
    
    dependencies {
        implementation("androidx.multidex:multidex:2.0.1")
    }
    
  2. Application geçersiz kılma durumunuza bağlı olarak sınıfını kullanmak istiyorsanız aşağıdakilerden birini gerçekleştirin:
    • Application ayarını geçersiz kılmazsanız sınıfını değiştirmek için manifest dosyanızı android:name <application> etiketi şu şekildedir:

      <?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.myapp">
          <application
                  android:name="androidx.multidex.MultiDexApplication" >
              ...
          </application>
      </manifest>
      
    • Application ayarını geçersiz kılarsanız sınıfını, MultiDexApplication öğesini aşağıdaki gibi uzatacak şekilde değiştirin:

      Kotlin

      class MyApplication : MultiDexApplication() {...}
      

      Java

      public class MyApplication extends MultiDexApplication { ... }
      
    • Application ayarını geçersiz kılarsanız ancak temel sınıfı değiştirmek mümkün değilse bunun yerine attachBaseContext() yöntemini geçersiz kılın ve etkinleştirmek için MultiDex.install(this) yöntemini çağırın multidex:

      Kotlin

      class MyApplication : SomeOtherApplication() {
      
          override fun attachBaseContext(base: Context) {
              super.attachBaseContext(base)
              MultiDex.install(this)
          }
      }
      

      Java

      public class MyApplication extends SomeOtherApplication {
        @Override
        protected void attachBaseContext(Context base) {
           super.attachBaseContext(base);
           MultiDex.install(this);
        }
      }
      

      Dikkat: Yürütme Yansıma yoluyla MultiDex.install() veya başka bir kod MultiDex.install() tamamlanmadan önce JNI adresine gönderin. Multidex izleme, bu çağrıları takip etmediğinden ClassNotFoundException veya doğrulama hataları (DEX dosyaları arasındaki hatalı sınıf bölümü nedeniyle)

Artık uygulamanızı oluşturduğunuzda Android geliştirme araçları birincil bir DEX oluşturur. dosyası (classes.dex) ve destekleyen DEX dosyaları (classes2.dex, classes3.dex vb.) ekleyebilirsiniz. Ardından, derleme sistemi tüm DEX dosyalarını APK'nıza paketler.

Çalışma zamanında, sadece ana aramada classes.dex dosyası yüklediğinizde, multidex API'ler tüm web sayfalarını aramak için özel bir sınıf yükleyici yöntemleriniz için kullanılabilir DEX dosyaları oluşturun.

Multidex kitaplığıyla ilgili sınırlamalar

Multidex kitaplığının bilinen bazı sınırlamaları vardır. Kitaplığı, uygulama derleme yapılandırmanıza eklerken aşağıdakileri göz önünde bulundurun:

  • Başlatma sırasında DEX dosyalarının bir cihazın veri bölümüne yüklenmesi karmaşıktır ve ikincil DEX dosyaları büyükse Uygulama Yanıt Vermiyor (ANR) hatalarına neden olabilir. Alıcı: bu sorunu önleyin, içeriği en aza indirmek için kod küçültmeyi etkinleştirin DEX dosyalarının boyutunu büyütebilir ve kodun kullanılmayan bölümlerini kaldırabilirsiniz.
  • Android 5.0'dan (API düzeyi 21) önceki sürümlerde çalışırken multidex, doğrusal sınırı aşmak için yeterli değildir (sorun 37008143). Bu sınır şu tarihte artırıldı: Android 4.0 (API düzeyi 14) yüklü ancak bu da sorunu tamamen çözmedi.

    Android 4.0'dan daha düşük sürümlerde, DEX endeksi sınırına ulaştı. Şundan daha düşük API düzeylerini hedefliyorsanız: 14. Platformun bu sürümlerinde kapsamlı bir test yapın çünkü uygulamanız başlangıçta veya belirli sınıf grupları yüklenirken sorun yaşıyorsa.

    Kod daraltma ortadan kaldırabilirsiniz.

Birincil DEX dosyasında gerekli sınıfları bildirme

Derleme araçları, multimedya uygulamaları için her DEX dosyasını oluştururken birincil DEX'te hangi sınıfların gerektiğini belirlemek için karmaşık karar alma süreçleri ekleyerek uygulamanızın başarılı bir şekilde başlatılmasını sağlayabilirsiniz. Zorunlu olan herhangi bir sınıfsa birincil DEX dosyasında sağlanmamışsa uygulamanız kilitleniyorsa java.lang.NoClassDefFoundError hatasıyla.

Derleme araçları, doğrudan uygulamanızdan erişilen kodun kod yollarını tanır girin. Ancak bu sorun, kod yolları daha az görünür olduğunda (ör. kullandığınız bir kitaplıkta ve karmaşık bağımlılıkları ifade eder. Örneğin, kodda iç gözlem veya çağrı kullanılıyorsa sınıfları farklı bir şekilde tanınmayabilir. birincil DEX dosyasında olması gerekir.

java.lang.NoClassDefFoundError alırsanız: birincil DEX'te gerekli olan ek sınıfları manuel olarak belirtmelidir dosyasını derleme türünüzde multiDexKeepProguard özelliğiyle tanımlayarak oluşturun. Bir sınıf multiDexKeepProguard dosyasını, ardından bu sınıfı birincil DEX dosyasına eklenir.

multiDexKeepProGuard mülkü

multiDexKeepProguard dosyası, ProGuard ile aynı biçimi kullanır ve tüm ProGuard dilbilgisi. Uygulamanızda nelerin depolandığını nasıl özelleştireceğinizle ilgili daha fazla bilgi için Hangi kodun saklanacağını özelleştirin.

multiDexKeepProguard ürününde belirttiğiniz dosya -keep içermelidir seçenekleri kullanılabilir. Örneğin, -keep com.example.MyClass.class Şu adla bir dosya oluşturabilirsiniz: multidex-config.pro gibi görünen kod:

-keep class com.example.MyClass
-keep class com.example.MyClassToo

Bir paketteki tüm sınıfları belirtmek istiyorsanız dosya aşağıdaki gibi görünür:

-keep class com.example.** { *; } // All classes in the com.example package

Ardından bu dosyayı aşağıdaki şekilde bir derleme türü için tanımlayabilirsiniz:

Eski

android {
    buildTypes {
        release {
            multiDexKeepProguard file('multidex-config.pro')
            ...
        }
    }
}

Kotlin

android {
    buildTypes {
        getByName("release") {
            multiDexKeepProguard = file("multidex-config.pro")
            ...
        }
    }
}

Geliştirme derlemelerinde multidex'i optimize edin

Multidex yapılandırması, derleme işlemede önemli ölçüde artış gerektirir çünkü derleme sisteminin hangi sınıfların mutlaka birincil DEX dosyasına ve hangi sınıfların ikincil DEX dosyaları olabilir. Yani, genellikle multidex kullanan artımlı derlemeler ve geliştirme sürecinizi yavaşlatabilir.

Artımlı derleme sürelerini azaltmak için önceden ekleme özelliğiyle derlemeler arasında multidex çıktılarını yeniden kullanın. Dizine ekleme için yalnızca Android 5.0'da kullanılabilen bir ART biçimi kullanılır. (API düzeyi 21) ve sonraki sürümler. Android Studio kullanıyorsanız IDE, otomatik olarak önceden ekleme özelliğini kullanır . Ancak Gradle derlemelerini komut satırından çalıştırıyorsanız Önceden dizine eklemeyi etkinleştirmek için minSdkVersion - 21 veya daha yüksek bir sayı girin.

uygulamanızın iki sürümünü oluşturabilirsiniz. aromalarını kullanarak: tek sürüm bir sürümü de yayın aroması vardır. minSdkVersion için farklı değerlere gösterildiği gibi:

Eski

android {
    defaultConfig {
        ...
        multiDexEnabled true
        // The default minimum API level you want to support.
        minSdkVersion 15
    }
    productFlavors {
        // Includes settings you want to keep only while developing your app.
        dev {
            // Enables pre-dexing for command-line builds. When using
            // Android Studio 2.3 or higher, the IDE enables pre-dexing
            // when deploying your app to a device running Android 5.0
            // (API level 21) or higher, regardless of minSdkVersion.
            minSdkVersion 21
        }
        prod {
            // If you've configured the defaultConfig block for the production version of
            // your app, you can leave this block empty and Gradle uses configurations in
            // the defaultConfig block instead. You still need to include this flavor.
            // Otherwise, all variants use the "dev" flavor configurations.
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }
    }
}
dependencies {
    implementation "androidx.multidex:multidex:2.0.1"
}

Kotlin

android {
    defaultConfig {
        ...
        multiDexEnabled = true
        // The default minimum API level you want to support.
        minSdk = 15
    }
    productFlavors {
        // Includes settings you want to keep only while developing your app.
        create("dev") {
            // Enables pre-dexing for command-line builds. When using
            // Android Studio 2.3 or higher, the IDE enables pre-dexing
            // when deploying your app to a device running Android 5.0
            // (API level 21) or higher, regardless of minSdkVersion.
            minSdk = 21
        }
        create("prod") {
            // If you've configured the defaultConfig block for the production version of
            // your app, you can leave this block empty and Gradle uses configurations in
            // the defaultConfig block instead. You still need to include this flavor.
            // Otherwise, all variants use the "dev" flavor configurations.
        }
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android.txt"),
                                                 "proguard-rules.pro")
        }
    }
}

dependencies {
    implementation("androidx.multidex:multidex:2.0.1")
}

Derleme hızlarını iyileştirmeye yardımcı olacak daha fazla stratejiyi Android Studio'dan veya Derleme hızınızı optimize etme bölümünü okuyun. Derleme varyantlarını kullanma hakkında daha fazla bilgi için bkz. Derleme varyantlarını yapılandırın.

İpucu: Farklı cihazlar için farklı derleme varyantlarınız varsa çokludex gereksinimleri varsa her biri için farklı bir manifest dosyası sağlayabilirsiniz için yalnızca API düzeyi 20 ve önceki sürümler için olan dosya <application> etiket adı. Ayrıca transkriptinizi Her varyant için farklı bir Application alt sınıfı oluşturun. API düzeyi 20 ve önceki sürümlerin altındaki alt sınıf, MultiDexApplication sınıfını veya MultiDex.install(this) numaralı telefonu arar.

Multidex uygulamalarını test edin

Multidex uygulamaları için araç testleri yazdığınızda ek yapılandırma gerekmez bir MonitoringInstrumentation veya bir AndroidJUnitRunner enstrümantasyon. Başka bir Instrumentation onCreate() yöntemini aşağıdaki kodla geçersiz kılmanız gerekir:

Kotlin

fun onCreate(arguments: Bundle) {
  MultiDex.install(targetContext)
  super.onCreate(arguments)
  ...
}

Java

public void onCreate(Bundle arguments) {
  MultiDex.install(getTargetContext());
  super.onCreate(arguments);
  ...
}