随着android平台的增长,同样你的应用也在迭代中,当你的app或者你应用的库到达一定的规模时,当我们build的时候很容易达到android的65k限制,早期build时的错误提示如下
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
最近几个版本中build时的错误提示如下
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
这两种错误情况显示一个共同的数字:65,536。这个数字是在它代表一个Dalvik可执行(DEX)字节码文件中调用或引用的方法总数。如果你已经建立了一个Android应用程序,并收到此错误,那么恭喜你,你的代码超过了一个DEX文件的限制!本文档介绍了如何将突破这个限制,并继续构建应用程序。
1,关于64K参考限值
Android应用(APK)文件包含在可执行的Dalvik(DEX)文件,其中包含用于运行你的应用程序的编译代码形式的可执行字节码文件。在Dalvik可执行的规范限制了可以在单个文件DEX内引用到65536,包括Android框架方法,库方法,并在自己的代码方式方法的总数。在计算机科学的上下文中,术语基洛,K表示1024(2 ^10)。因为65,536等于64×1024,这个限制被称为’64K参考限制’。
如果想突破此限制,您需要配置您的应用程序的构建过程,生成多个文件DEX,被称为multidex配置。
2,Multidex支持到Android5.0之前
之前的Android5.0(API级别21)平台的版本,用于执行应用程序代码的Dalvik运行。默认情况下,Dalvik的限制应用到每个APK一个classes.dex字节码文件。为了解决这个限制,可以使用multidex支持库,成为您的应用程序的主DEX文件的一部分,然后设法获得额外的DEX文件和它们所包含的代码。
注意:如果您的项目配置为multidex用的minSdkVersion20或更低,并且部署到目标运行Android4.4(API级别20)或更低的设备,Android Studio中禁用即时运行。
3,为Android5.0及更高版本Multidex支持
Android 5.0(API级别21)和较高的使用一种称为ART运行时它本身支持与应用程序APK文件加载多个DEX文件。 ART在应用程序执行预编译安装时它会扫描类(.. N).dex文件,并将其编译成由Android设备执行单一.oat文件
注意:使用即时运行,当你的应用程序的的minSdkVersion设置为21或更高版本的Android Studio自动配置您的应用程序的multidex。由于即时只运行与您的应用程序的调试版本的作品,你还需要为multidex配置您的发布版本,以避免64K限制。
4,避免64K限制
在配置您的应用程序,以便使用64K或以上方法的引用,您应该采取措施,以减少你的应用程序代码调用引用的总次数,包括您的应用程序代码或包含的库定义的方法。以下策略可以帮助您避免击中DEX参考限值:
查看应用的直接和传递依赖 - 确保任何大库的依赖关系,你在应用程式的方式,胜过的代码量被添加到应用程序中使用。一个常见的反模式是包含一个非常大的库,因为一些实用的方法是有用的。减少你的应用程序代码依赖性往往可以帮助你避免DEX参考限值。
使用ProGuard删除未使用的代码 - 为您的应用程序配置ProGuard的设置来运行ProGuard,可以只对你使用到的code进行编译,其他的不会加载到dex文件中
使用这些技术可以帮助您避免使你的应用更多方法引用所需的生成配置的变化。这些步骤还可以降低你的APK,当流量费比较高的情况下,这种方式也是比较可取的
5,在Gradle中配置Multidex
因为要在Android SDK build tools 2.1.1及以后的版本中,Gradle插件才可以直接配置使用multidex,所以在使用之前,确保你的Android SDK build tools版本,可以通过SDK Manager来进行在线升级
编辑Gradle确保multidex可用
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
...
minSdkVersion 14
targetSdkVersion 21
...
// Enabling multidex support.
multiDexEnabled true
}
...
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}
当这些配置设置添加到应用程序,Android编译工具构建需要一个主DEX(classes.dex)及其配套(classes2.dex,classes3.dex)。然后,构建系统将它们打包成用于分配的APK文件。
注意:如果您的应用程序继承了Application,则可以覆盖attachBaseContext()方法,并调用MultiDex.install(context);
6, MultiDex的使用限制
当使用MultiDex的时候应该了解一些他的限制和测试
DEX文件启动期间安装到设备的数据分区是复杂的,并可能导致在应用无响应(ANR)错误如果二次DEX文件比较大。在这种情况下,你应该使用ProGuard尽量减少DEX文件的大小,并删除代码的未使用的部分。
由于Dalvik的linearAlloc错误(22586期)multidex可能无法运行,Android 4.0之前的(API级别14)平台版本的设备启动应用程序。如果你是早于14 API目标水平,确保执行与这些版本的平台测试您的应用程序可以在启动时没问题或当某类class类被加载
使用multidex配置,使非常大的内存分配请求的应用程序可能在运行时由于Dalvik的linearAlloc限制(问题78035)崩溃。此分配限制是在Android 4.0的(API级别14)增加,但应用仍有可能之前的Android 5.0(API级别21)碰上在Android版本中此限制。
7,优化Multidex开发版本
一个multidex配置需要Gradle很长的处理时间,因为构建系统必须做出什么类必须包含在主DEX文件,哪些类可以包含在二次DEX文件复杂的决定。这意味着,常规建立与multidex发展过程的一部分执行通常需要更长的时间,并有可能减缓您的开发过程。
为了减轻通常较长的建立multidex输出时间,你应该创建使用Gradle中的productFlavors的Android插件构建输出两个变化:development flavor and a production flavor.
对于development flavor,支持SDK最小版本2.1,采用 ART-supported format,apk Multidex更快
对于 release flavor,最小版本就是project的minSdk,此设置生成APK multidex是与更多的设备兼容,但需要更长的时间来建立。
下面构建配置示例演示了如何设置Gradle:
android {
productFlavors {
// Define separate dev and prod product flavors.
dev {
// dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
// to pre-dex each module and produce an APK that can be tested on
// Android Lollipop without time consuming dex merging processes.
minSdkVersion 21
}
prod {
// The actual minSdkVersion for the application.
minSdkVersion 14
}
}
...
buildTypes {
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}
完成此配置更改后,您可以使用您的应用程序,它结合了开发productFlavor和调试buildType的属性devDebug变种。,multidex调试应用程序启用,并设置的minSdkVersion到Android API21这些设置导致了Android gradle这个插件来做到以下几点:
建设作为单独的DEX文件的应用程序(包括依赖)的每个模块。这通常被称为pre-dexing
确保每个apk中的dex文件不能修改
最重要的是,模块DEX文件将不会合并,所以长期运行计算来确定主DEX文件的内容是可以避免的。
这些设置会导致快速,增量编译,因为只有修改模块的DEX文件重新计算和重新包装成APK文件。从这些结果APK建立可用于仅5.0设备在Android上进行测试。然而,通过实现配置作为flavar后,将保留执行正常的生成与释放,适当的最低水平SDK和ProGuard的设置的能力。
还可以构建其它变体,包括一个prodDebug变种的构建,这需要更长的时间来建立,但可以用于测试开发之外。在所示的配置中,prodRelease变异将是最后的测试和发布版本。如果您在命令行中执行任务的gradle,您可以使用带有DevDebug标准命令追加到结尾(例如./gradlew installDevDebug)。
提示:您还可以提供定制manifest,每个flavar对应一个application,允许您使用支持库MultiDexApplication类,或调用MultiDex.install()只对需要它的变种。
8,在android studio中使用Build Variants
Build Variants可以使用多DEX时,管理构建过程非常有用的。 Android Studio中,您可以选择在用户界面构建这些Variants。
有Android Studio中建立自己的应用程序的“devDebug”Variants:
打开从左边的侧边栏生成Variants窗口。该选项旁边的收藏夹。
单击构建变量的名称,以选择一个不同的Variants中,如图1
图1显示了构建Variants在Android Studio的左侧面板的屏幕截图。
注:打开此窗口中的选项只在您成功同步Gradle build file using the Tools > Android > Sync Project with Gradle Files command.
9,测试 Multidex Apps
当使用仪器测试,multidex应用程序,则需要额外的配置,以使测试仪器。由于代码在multidex应用类的位置不是一个单一的DEX文件内,仪表测试不正确除非配置为multidex运行。
为了测试与仪器测试中multidex应用程序,从multidex测试支持库配置MultiDexTestRunner。下面的示例的build.gradle文件演示了如何配置您的构建来使用这个测试运行:
android {
defaultConfig {
...
testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
}
}
当Gradle版本小于1.1时,需要添加multidex-instrumentation:依赖
dependencies {
androidTestCompile('com.android.support:multidex-instrumentation:1.0.1') {
exclude group: 'com.android.support', module: 'multidex'
}
}
您可以直接使用 instrumentation test 运行的类或扩展,以满足您的测试需求。或者,您可以在这样现有的 instrumentation test 覆盖的onCreate:
public void onCreate(Bundle arguments) {
MultiDex.install(getTargetContext());
super.onCreate(arguments);
...
}
注:目前不支持multidex创建APK测试使用。
原文来自:
https://developer.android.com/studio/build/multidex.html#dev-build