Multidex 和 Dex 方法限制
什么是 dex?
Dex 是编译 Android Java 代码的文件格式和编码的名称。早期版本的 Android 将直接在名为 Dalvik 的虚拟机中加载和执行 dex
二进制文件。更新版本的 Android 使用 Android Runtime(ART)
,它将 dex
文件视为中间表示,并在运行应用程序之前对其进行进一步编译。
就智能手机的使用寿命而言,Dex 是一种非常古老的文件格式,专为主存在数十兆字节的设备而设计。那些日子的设计局限一直延续至今。
问题:
dex
文件格式对可在单个二进制文件中引用的方法数量进行编码。由于存储引用数的文件格式部分长度为两个字节,因此最大方法引用数为 0xFFFF
或 65535.如果应用程序包含的方法引用数超过该数量,则无法编译。
该怎么做:
Google 提供了解决此问题的方法,称为 Multidex。它具有编译时和运行时组件。顾名思义,在编译时它会在一个或多个 dex
文件之间划分代码。在运行时,它将教授默认的 ClassLoader
如何从这些文件中查找类。
这种方法适用于较新的设备,但有一些实质性的缺点。它可以显着增加应用程序启动时间,而在较旧的设备上可能会导致 Application Not Responding
失败。
如果可能的话,应尽量避免使用 Multidex。
如何避免限制:
在配置应用程序以启用 64K 或更多方法引用之前,你应该采取措施减少应用程序代码调用的引用总数,包括应用程序代码或包含的库定义的方法。以下策略可以帮助你避免达到 dex 参考限制:
- 检查应用程序的直接和传递依赖关系 - 确保你在应用程序中包含的任何大型库依赖关系的使用方式超过了添加到应用程序的代码量。一个常见的反模式是包含一个非常大的库,因为一些实用方法是有用的。减少应用程序代码依赖性通常可以帮助你避免 dex 参考限制。
- 使用 ProGuard 删除未使用的代码 - 为应用程序配置 ProGuard 设置以运行 ProGuard,并确保为发布版本启用了收缩功能。启用收缩可确保你不会使用 APK 发送未使用的代码。
第一点需要开发人员的勤奋和纪律。合并第三方库时,必须考虑库的大小。例如,两个流行的 JSON 库是 Jackson 和 Gson。功能上它们非常相似,但 Gson 倾向于在 Android 中看到更多用途。一个原因是,杰克逊的重量约为 9,000 种,而 Gson 的贡献为 1,900 种。
有几种工具可以帮助开发人员跟踪他们的应用程序的大小:
- dexcount-gradle-plugin 报告每个构建中 APK 或 AAR 中的方法引用数
- dex-method-counts 是一个命令行工具,用于计算 APK 中方法引用的数量
- www.methodscount.com 是一项网络服务,可以计算你上传的任何 APK 中的方法参考。