Multidex解惑

做安卓开发的应该都遇到过这样一个问题:
在这里插入图片描述
典型的引用方法超过了65536的错误,构建的时候会报错;
为什么会这样呢?
  65536是单个dex文件内可调用的方法数,google用的是个short int;
那dex文件又是什么?
  dex文件是之前dalvik虚拟机上执行的文件(5.0开始是AOT),类似jvm虚拟机执行的是字节码文件;
  随着应用程序越来越大,包含的方法越来越多,就产生了以上问题,为了解决以上问题:谷歌提供了一些官方的方法:

  Android5.0之前的平台版本使用dalvik来执行应用的代码,dalvik限制使用单个dex文件;要想绕过这个限制,使用dalvik可执行文件分包支持库,它会成为主dex文件的一部分,然后管理其他dex文件以及所包含代码的访问。
  Android5.0及以上平台使用ART运行时方式,支持从apk文件加载多个dex文件,ART再安装是执行预编译,扫描多个.dex文件,并将它们编译成一个.oat文件,供Android设备执行。

规避64k限制,谷歌提供的方法:

  1. 首先得先检查大的依赖和传递依赖(怎么检查):确保引用大的依赖所带来的好处大于所带来的弊端。
  2. 通过ProGuard移除未使用的代码:启用代码压缩,确保交付的apk不含有未使用的代码;(怎么用)

配置应用dalvik可执行文件分包

如果minSdkVersion >=21,只需要在build.gradle文件中,如图:
Multidex解惑_第1张图片
如果minSdkVersion <=20,除了multiDexEnabled 设置为true,还需要
在这里插入图片描述
如果没有替换过Application类,那么

public class MyApplication extends MultiDexApplication { ... }

如果替换过Application,那么

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

配置好之后,Android构建工具会根据需要构建主dex,辅助dex1,辅助dex2等,构建系统会吧所有dex文件打包成apk文件;

分包支持库的局限性:

  1. 如果辅助dex比较大,可能会引起ANR,在这种情况下,应该用proguard尽量减少dex文件大小;
  2. 使用 Dalvik 可执行文件分包的应用可能无法在运行的平台版本早于 Android 4.0(API 级别 14)的设备上启动;
  3. 如果使用 Dalvik 可执行文件分包配置的应用发出非常庞大的内存分配请求,则可能会在运行期间发生崩溃;

声明主dex文件中需要的类

  为dalvik可执行文件构建每个dex时,构建工具会执行复杂的决策确定主dex文件中需要的类,如果启动期间需要的任何类未在主 DEX 文件中提供,那么您的应用将崩溃并出现错误 java.lang.NoClassDefFoundError;
  如果收到 java.lang.NoClassDefFoundError的错误,则可以用multiDexKeepFile或者multiDexKeepProguard属性声明,以手动将这些类指定为主dex必须项;

multiDexKeepFile属性
在 multiDexKeepFile 中指定的文件应该每行包含一个类,并且采用如下格式:

com/example/MyClass.class
com/example/MyOtherClass.class

然后,您可以按以下方式针对构建类型声明该文件:

android {
    buildTypes {
        release {
            multiDexKeepFile file('multidex-config.txt')
            ...
        }
    }
}

请记住,Gradle 会读取相对于 build.gradle 文件的路径,因此如果 multidex-config.txt 与 build.gradle 文件在同一目录中,以上示例将有效。

multiDexKeepProguard属性
  multiDexKeepProguard 文件使用与 Proguard 相同的格式,并且支持整个 Proguard 语法。如需了解有关 Proguard 格式和语法的详细信息;
  在 multiDexKeepProguard 中指定的文件应该在任何有效的 ProGuard 语法中包含 -keep 选项;如下:

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

如果您想要指定包中的所有类,文件将如下所示:

-keep class com.example.** { *; }

然后,您可以按以下方式针对构建类型声明该文件:

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

你可能感兴趣的:(Android)