Android MultiDex - 关于内部工作的问题

AnD*_*123 9 android android-build android-activity android-gradle-plugin android-multidex

我最近发现了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文件中,还是根据它们包含在模块中?

Ale*_*pov 16

什么是主要的dex?

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

收集{variant} MultiDexComponents任务

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

收缩{variant} MultiDexComponents任务

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

创建{variant} MainDexClassList任务

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

如果我的minSdk是21,会发生什么?

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


tho*_*ers 4

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

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

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

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