当app和依赖的库,所有的接口数超过65536,编译时会遇到错误,提示接口超过了限制,log如
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
老版本编译系统会报一个不同形式的错误log
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
这两种形式的log都有一个相同的数字:65536。这个数字代表了单个虚拟机执行DEX文件可调用接口的最大数。本文解释如何通过多dex文件解决之前的接口限制,使app可以编译和读多dex文件。
Android app包含虚拟机执行的DEX格式的bytecode文件,该文件是编译代码所得。虚拟机执行规范规定了单个dex文件包含的最大接口数为65536,这些接口可以是:Android framework接口、库接口、app接口。
dependencies {
def multidex_version = "2.0.1"
implementation 'androidx.multidex:multidex:$multidex_version'
}
如果要看库的当前版本,在version页面查看Multidex。
如果不使用AndroidX,使用下面的库代替
dependencies {
implementation 'com.android.support:multidex:1.0.3'
}
这个库会成为主dex文件的一部分,用来管理其他的dex文件和获取其中的代码。
在使能多dex支持前,尽量减少app和库的接口,使用以下策略帮助避免遭遇dex接口限制:
使用这些技术可以帮助避免使用多dex同时减小apk的整体大小。
Android5.0及以上版本已默认支持,无需额外配置,低版本系统已经很少,因此这里不做说明。
若需了解,参考“Enable multidex”的Configure your app for multidex
章节。
支持多dex的app编译时,会明显的增加编译时间,因为在编译时有一个复杂的决定过程,需要决定哪些class放在主dex,哪些class可以放在非主dex中。这意味着使用多dex而增加的编译可能会延长开发周期。
为了缓和增加的时间,在多次编译间使用dex预处理,减少多dex输出需要的时间。dex预处理依赖Android5.0及之上版本支持的ART。如果AndroidStudio版本为2.3或更高,在Android5.0及之上版本,编译时自动使用预处理功能。
注意: Android gradle插件3.0及更高版本有改善编译速度的特性,如每个class文件做dex处理,当class文件被修改了,才会再次做dex。通常情况下,最佳的开发体验是,及时更新AndroidStudio和插件为最新。
如果使用命令行编译app,需要在脚本中配置minSdkVersion为21或更高,以使支持编译dex预处理。一个有用的策略是增加一个编译变体,在编译变体中配置minSdkVersion。示例如下:
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 what you set for
// 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 'com.android.support:multidex:1.0.3'
}
注意: 当编译app的最低版本不小于21,命令行编译也无需新增编译变体。
当使用instrumentation tests测试多dex app时,使用MonitoringInstrumentation (or an AndroidJUnitRunner) instrumentation
无任何附加配置。如果使用Instrumentation
,必须重写onCread且添加如下代码
public void onCreate(Bundle arguments) {
MultiDex.install(getTargetContext());
super.onCreate(arguments);
...
}