降低启动速度的问题
文章中提到的一点,在 Android 设备 4.4 及其之前的版本,当开启 Multidex 的时候,启动速度会延长 15% 。而 5.0及以上的设备因使用 ART 的方式,其默认支持多 dex 的加载。
NoClassDefFoundError 的问题
- 查看加载的类问题 在目录 [buildDir]/intermediates/multi-dex/[buildType]/maindexlist.txt 中可查看在主 dex 文件中的类,(但并不是 100% 准确,可能会丢失一些类)
- 解决办法:配置一个新的 multidex.keep 文件,用来指定在 mainDex 中包含的类。通过配置 gradle 文件,指定 gradle 打包过程中,执行 dex 生成时的 keep 文件追加。具体实施是创建一个新的 task,使用 finalizedBy 来指定在 create**MainDexClassList 任务之后执行。另外还需要指定 dx 执行时,添加 –minimal-main-dex 选项,来使 maindex 最小化。
如何判断 App 启动过程中哪些类是需要加载的呢?
通过使用类加载 ClassLoader 中,其提供了方法 findLoadedClass。这个方法的作用是用来判断某个类是否被加载,所以文章中使用的技巧就是通过读在 second dex files 中的类,来判断主 dex 是否加载到。若是加载到,则我们就需要将这个类添加至 main dex 来提高 App 的启动速度。
解决与建议
出现 65k 的问题时候,通过其他方式(重构、优化第三方 SDK的使用)来尽量避免使用 Multidex;若是不可避免地使用,需要对 Multidex 的方式进行优化来使用,来尽量提高我们 App 的启动速度。
延迟加载
对纯 java 文件,可以将其单独打成一个 dex,利用 Multidex 加载的原理,在当我们使用到相应 java 文件的时候,再加载这个 dex,来执行相应代码的调用。(方案有些不成熟,不支持涉及到资源文件的情况。)
其他
1. 工具 ClassShark
在评论区,提到的一个软件 android-classyshark,可以帮我们更加容易分析 APK、dex、jar 中的使用内容,(不再通过 dex2jar, jd-gui等工具来查看)能够对 apk 中的内容一目了然, 功能非常强大。
在 Android Studio 2.2 之后的版本,其已经支持了对 apk 的分析,可以直接点击进行查看。
2. dex2oat 与 dexopt
评论中关于 5.0及以上不受影响的讨论,主要原因是因为 5.0 采用了 ART 的编译方式,其是在 app 安装的时候执行的,期间对 dex 文件采用了 dex2oat 的执行过程,来对 dex 文件进行优化。而 5.0 之前的设备是没有这一步,其采用的 dexopt 的过程,并处理的是单个 dex 文件,这样也会影响了 multidex 的启动速度,但是这个是每次打开 app 都会进行的,并不是安装时执行的。
作者的关注点是在每次 App 打开的过程中, Multidex 带来的影响,所以这个讨论在这里并不是与主题太多相关,但是我们还是又必要了解一下的。