9

我最近发现了来自 Android 的新 MultiDex 功能,用于处理具有 65,000 多个引用的应用程序。见:https ://developer.android.com/tools/building/multidex.html

有人可以帮我理解以下问题:

1) Gradle 构建插件如何确定在主 dex 文件 (classes.dex) 和辅助 dex 文件中放置什么?根据文档,主 dex 中需要某些东西,但它没有给出任何示例。所有活动都必须在主 dex 文件中吗?

引用文字:

在 Dalvik 运行时执行时,对于主 dex 文件中需要哪些类有复杂的要求。Android 构建工具更新处理 Android 需求,但其他包含的库可能有额外的依赖要求,包括使用自省或从本机代码调用 Java 方法。在更新 multidex 构建工具以允许您指定必须包含在主 dex 文件中的类之前,某些库可能无法使用。

2) 仅针对 Android API Level 21 (Android L) 及更高版本构建时,Gradle Build Plugin 中的行为有所不同。它说它要快得多,因为它“将应用程序的每个模块(包括依赖项)构建为单独的 dex 文件。这通常称为预 dexing。” Android中模块的定义是什么?这是这里提到的 Java 库、Android 库和 Android 应用程序模块:http: //developer.android.com/sdk/installing/studio-build.html#projectModules?远程或本地二进制依赖项(例如:Jars)是否算作单独的模块,因此会被放入不同的 dex 文件中,还是根据它们被包含在模块中?

4

2 回答 2

18

main-dex 中放置了什么?

有三个顺序任务来计算应该在 main dex 中打包哪些类:

收集{variant}MultiDexComponents 任务

该任务根据清单将所有应用程序组件(应用程序、活动、服务、接收者、提供者)的类名写入文本文件。也就是说,如果您有一个未在清单中注册的组件,它将不会放在 main-dex 中。还有其他非清单类 - 例如注释。要查看完整列表,请查看插件源中的CreateManifestKeepList.groovy任务。
此任务的输出是 manifest_keep.txt 文件。

收缩{variant}MultiDexComponents 任务

此任务调用 ProGuard 来创建一个缩小的 jar,其中仅包含 manifest_keep.txt 文件中提到的类。
此任务的输出是 componentClasses.jar 文件。

创建{variant}MainDexClassList 任务

此任务采用 componentClasses.jar 文件,并为每个类计算直接引用层次结构(有关更多信息,请参阅实现)。也就是说,如果您的一个组件类有一个类型为 X 的字段,那么这个 X 类也将被添加到 main-dex 列表中。
此任务的输出是 maindexlist.txt,其中包括将打包到主 dex 中的所有类的列表。

如果我的 minSdk 是 21 会怎样?

如果您的 minSdk 版本为 21,则上述任务均不会运行 - 无需计算 main-dex 列表。这是因为在 ART 中,所有 dex 文件在应用安装期间都转换为单个 .oat 文件。因此不需要运行时 ClassLoader 补丁。

于 2014-11-29T22:44:58.580 回答
4

1)gradle插件内部使用Proguard在intermediates/multi-dexbuild文件夹下创建两个jar文件。一个将是主要的 dex,其余的将分布在 dex 2、3 等上。

collect{variant}MultiDexComponents任务负责为proguard创建keep文件,你可以在我上面提到的文件夹的variant specific子目录中看到这个文件和其他proguard参数。希望从长远来看,这将是可定制的。

目前在 gradle 插件 ( https://code.google.com/p/android/issues/detail?id=80741 ) 的 1.0.0-rc1 中还有一个与测试项目相关的错误。通过一些小的更改,我在那里发布的解决方法也可用于立即将您自己的条目添加到保留列表中(从而确保您的类最终在主 dex 中)。

2) 模块从 Gradle 的角度指代模块,但这些确实可以是您链接到的列表中提到的不同项目。--info如果您使用作为标志从命令行执行 pre-lollipop gradle 构建,您可以看到所有 dex 文件被传递到dx. (请注意,这不应该是启用了 multidex 的构建或带有 的构建preDexLibraries = false)。

于 2014-11-25T13:28:31.677 回答