Android 的 multidex 可以使用maindexlist来指定哪些包的class放在第一个dex中,但却要我们自己手动指定,而且不能使用正则或者其他通配符指定,非常不方便。
Android的gradle构建方式给自定义构建带来很大的便利。你可以在自己的项目中增加一个buildSrc的module来专门处理一些构建时要用到的自定过程,可以使用groovy或者Java来编写。
本着对新事物探索的热爱,我也是一边学gradle一边试着用。从最开始在build.gradle中进行dex指定分包,到现在的可以配置化的Dex分包的gradle插件,也是走过一条长路。
===================================
更新:
1.5.9: 兼容一些古老的 gradle 和 android gradle plugin版本
1.5.8: 兼容gradle 3.2,修复当只使用support-split/support-keep时出现大量的额外类
1.5.7: 修复support-split/support-keep无效的bug
1.5.6:支持java 1.7,修复但只有keep选项时没有类被选中
1.5.5: 单独的maindexlist过滤设置
1.5.5.alpha: 实验性的支持 2.2.0 plugin
1.5.4: instant run 模式时自动禁用DexKnife
1.5.3: 增加跟踪日志,并在jarMerging为null时跳过处理
1.5.2: 修复include和exclude, 并支持过滤单个类(使用'.class'作为单个类的后缀)
1.5.1.exp 版本可以支持2.0以上的plugin
==============================
注意:DexKnife 本身只适用于将配置的通配符生成maindexlist,无法进行多个dex指定。
言归正传,指定dex分包插件为gradle-dexknife-plugin,使用他只需要做几件事:
1、com.android.tools.build:gradle 的版本可以是大于1.3.0的任何版本。
2.0.0以上的instant-run 与 multidex不兼容。在instant-run模式下,DexKnife会暂时自动禁用,在release打包时会自动启用。instant-run 采用新的打包模式,不会出现数量溢出的问题。
2、在项目的build.gradle 增加依赖,我发把他发布到jcenter上了(先检查您的网络是否可达):
buildscript {
...
dependencies {
....
classpath 'com.ceabie.dextools:gradle-dexknife-plugin:1.5.9'
}
}
注意,请确保使用的gradle版本和android gradle plugin兼容,否则会出现同步错误,例如:
Gradle sync failed: Unable to load class 'com.android.builder.core.EvaluationErrorReporter'.
3、在App的module的目录下增加dexknife.txt文件,并编辑你需要的配置
使用 # 进行注释, 当行起始加上 #, 这行配置被禁用.
# 全局过滤, 如果没设置 -filter-suggest 并不会应用到 建议的maindexlist.
# 如果你想要某个包路径在maindex中,则使用 -keep 选项,即使他已经在分包的路径中.
-keep android.support.v4.view.**
# 这条配置可以指定这个包下类在第二dex中.
android.support.v?.**
# 使用.class后缀,代表单个类.
-keep android.support.v7.app.AppCompatDialogFragment.class
# 不包含Android gradle 插件自动生成的miandex列表.
-donot-use-suggest
# 将 全局过滤配置应用到 建议的maindexlist中, 但 -donot-use-suggest 要关闭.
-filter-suggest
# 不进行dex分包, 直到 dex 的id数量超过 65536.
-auto-maindex
# dex 扩展参数, 例如 --set-max-idx-number=50000
# 如果出现 DexException: Too many classes in --main-dex-list, main dex capacity exceeded,则需要调大数值
-dex-param --set-max-idx-number=50000
# 显示miandex的日志.
-log-mainlist
# 如果你只想过滤 建议的maindexlist, 使用 -suggest-split 和 -suggest-keep.
# 如果同时启用 -filter-suggest, 全局过滤会合并到它们中.
-suggest-split **.MainActivity2.class
-suggest-keep android.support.multidex.**
'*' 匹配任意数量的字符
'?' 匹配任意一个字符
'**' 匹配任何类路径和类
'.' 和 '/' 都可用来指定类的分割.
'.' 或者 '/' 的结尾会自动增加 '**'.
例如,android.*.v?.** ,android.support.v7 和v4下的所有类都被分到的第二个dex中。
注意: 如果你要过滤内部类, 使用$*,例如: SomeClass$*.class
具体参考:https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/util/PatternFilterable.html
4、在你的App的module中的build.gradle中加插件:
apply plugin: 'com.ceabie.dexnkife'
注意:要在 defaultConfig 或者 buildTypes中打开 multiDexEnabled true,否则不起作用。
最后,运行的app,分包的东西就交给DexKnife了。祝好运。
(dexknife只会在配置变动或者代码变动的时候才会处理)
项目地址:https://github.com/ceabie/DexKnifePlugin
插件调试:http://blog.csdn.net/ceabie/article/details/55271161