一、起源
在Android项目中,添加了某一个第三方类库后,构建报错,提示java.lang.VerifyError
二、解决
于是google了一下,Android Doc文档给出的解释是,尝试去加载一个在验证阶段未通过的类,又看了stackoverflow上一些问题的解释,确定是APP Methods 个数超过65536导致的问题,要解决这个问题,需要使用multiDex,通过以下两步完成配置。
1.配置 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' }
2.在APP的Application配置MultiDex
1>如果未自定义Application
<application
...
android:name="android.support.multidex.MultiDexApplication">
...
</application>
2>如果自定义了Application,那么需要在Application的
attachBaseContext方法中配置multiDex
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
Tips:可能遇到的问题,如果只是在gradle中添加MultiDex选项,没有在Application中配置,当在项目中添加新的类时,编译不会报错,运行时,报Runntime Error Java.lang.ClassNotDefError.
三、延展
1.超长的编译时间
添加multiDex之后,编译时间超长,严重的影响了开发效率
在Android的官方网站查了下MultiDex相关的资料,找到了一些优化解决方案
1>原因:
当添加multiDex配置后,每次构建APP时,会把类分开到不同的dex文件,一个Primary Dex(classes.dex) 和多个Support Dex 文件(classes2.dex, classes3.dex),构建系统需要经过复杂的策略决定哪些类放到 Primary Dex文件,哪些类放到Support Dex中
2>优化方案
可以通过Android 的 productFlavors来优化这个问题
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' }在productFlavors中添加了两个变量,一个development,一个product,同步gradle之后,会生成四个构建变量 devDebug devRelease, prodDebug, prodRelease,在studio的Build Variants中配置在开发时,使用devDebug,发布时,使用prodRelease,
这样在开发的时候,设置的最低编译版本是21,发布时,使用的最低版本根据项目需要配置。
上述配置同步之后,平常开发时,构建的速度很快,只有发布Release版本时,构建才比较慢。
缺点时,debug的APK只能安装在5.0以上的机器中(推荐Genymotion的模拟器~确实非常好用)。
3>为什么能优化速度?
上述配置完成后,gradle在构建项目时:
①APP的每个module(包含依赖)被编译为单独的dex文件,作为预编译的dex文件被引用,Android 5.0使用ART作为默认方式
②APK文件只是把每个module的dex文件包含进来,不做任何改动
③最重要的一点,所有的dex文件不用再融合,这样构建系统就不用花费很长的时间去决定把哪些classes放到primary dex文件中
2.MultiDex support library的缺陷
1>APP在启动时,将dex文件安装到Data分区的过程变得复杂,如果第二个dex文件过大,可能导致ANR错误。如果出现这种情况,可以通过ProGuard来减小dex文件的大小,同时删除没有引用的代码
2>APP 不能在低于Android 4.0的版本启动
3>使用MultiDex机制的APP如果在运行时申请过大的内存,可能导致APP crash,因为Android 5.0之前的版本限制了Dalvik能够申请的内存
4>Dalvik虚拟机在运行时,对于哪些需要放在primary dex文件的class的需求时非常复杂的,有可能某些需要的类库并没有被放在primary dex文件中,导致运行时错误
四、参考资料
参考网址:
https://developer.android.com/tools/building/multidex.html#avoid
http://stackoverflow.com/questions/32205938/java-lang-noclassdeffounderror-android-support-v4-view-layoutinflatercompathc-i
http://frogermcs.github.io/MultiDex-solution-for-64k-limit-in-Dalvik/