在Android中单个dex文件所能包含的最大方法数是65536,这包含AndroidFrameWork、依赖的jar包以及应用本身的代码所包含的方法。一般来说,一个简单的应用的方法数很难达到65536,但对于一些大型项目来说,就很容易达到了。当应用的方法数达到65536时,编译器就无法完成编译工作并抛出DexIndexOverflowException异常。
还有一种情况,有时候方法数并未达到65536,并且编译器也正常完成了编译工作,但是应用在低版本手机上安装异常终止。异常信息如下:
E/dalvikm: Optimization failed
E/installd: dexopt failed on '/data/dalvik-cache/data@app@com.ryg.multidextest-2.apk@classes.dex' res = 65280
出现这种情况的原因呢,是由于dexopt是一个程序,应用在安装时,系统会通过dexopt来优化dex文件,在优化过程中dexopt采用一个固定大小的缓冲区来存储应用中所有的方法信息,这个缓冲区就是LinearAlloc。LinearAlloc缓冲区在新版本的Android系统中其大小是8MB或者16MB,但是在Android2.2和2.3中只有5MB。当待安装的apk中的方法数比较多时,尽管它还没有达到65536这个上限,但他的存储空间仍然有可能超过5MB,这种情况下dexopt程序就会报错,从而导致安装失败,这种情况主要在2.x系列的手机上出现。
不管是编译方法数越界还是安装时的dexopt错误,他们都给开发过程带来了很大的困扰。为了解决这个问题,Google在2014年提出了multidex的解决方案。
multidex在Android Studio如何使用:
首先在app目录下的build.gradle文件中添加multiDexEnabled true这个配置项:
defaultConfig {
applicationId "com.example.myapplication"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
然后在dependencies中添加multidex的依赖:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0-beta01'
implementation 'com.android.support:multidex:1.0.0'
}
最后需要在代码中加入支持multidex功能,这个过程有三种方案可选:
1、在manifest文件中指定Application为MultiDexApplication;
<application
android:name="android.support.multidex.MultiDexApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
</application>
2、让应用的Application继承MultiDexApplication;
public class TestApplication extends MultiDexApplication {
...
}
3、如果不想让应用的Application继承MultiDexApplication,还可以选择重写Application的attachBaseContext方法,这个方法比Application的onCreate要先执行;
public class TestApplication extends Application {
@Override
protected void attachBaseContext(Context base){
super.attachBaseContext(base);
MultiDex.install(this);
}
}
完成上述几个步骤,可以防线应用不但编译通过并且还可以在Android2.x手机上正常安装了。