@@ -23,7 +23,7 @@ protected void attachBaseContext(Context base) {
23
23
```
24
24
25
25
###坑2:Too many classes in –main-dex-list ,what?
26
- ** 原因:** 通过上面的官方分包,已经把原Dex分为1主Dex加多从Dex,主Dex保留4大组件, Application,Annotation,multidex等及其必要的直接依赖。由于我们方法数已达到16W之巨,上百个Activity,所以成功的把主Dex又撑爆了 。
26
+ ** 原因:** 通过上面的官方分包,已经把原Dex分为1主Dex加多从Dex。主Dex包含所有4大组件, Application,Annotation,multidex等及其必要的直接依赖。由于我们方法数已达到16W之巨,上百个Activity全部塞进主Dex,又成功的把主Dex撑爆了 。
27
27
28
28
** 解决:**
29
29
gradle
@@ -42,37 +42,36 @@ afterEvaluate {
42
42
参考=>[ Android Dex分包之旅] ( http://yydcdut.com/2016/03/20/split-dex/index.html )
43
43
44
44
###坑3:gradle 1.5.0之后不支持这种写法 ,what the fuck?
45
- ** 原因:** 官方解释Gralde` 1.5.0 ` 以上已经将(jacoco, progard, multi-dex)统一移到[ Transform API] ( http://tools.android.com/tech-docs/new-build-system/transform-api ) 里,然而Transform API并没有想象的那么简单好用,最后翻遍Google终于找到一个兼容Gradle ` 1.5.0 ` 以上的分包插件[ DexKnifePlugin] ( https://github.com/ceabie/DexKnifePlugin ) 。
46
- 参考 =>这篇[ Android 热修复使用Gradle Plugin1.5改造Nuwa插件] ( http://blog.csdn.net/sbsujjbcy/article/details/50839263 ) 比较好的介绍了Transform API的使用。
45
+ ** 原因:** 官方解释Gralde` 1.5.0 ` 以上已经将(jacoco, progard, multi-dex)统一移到[ Transform API] ( http://tools.android.com/tech-docs/new-build-system/transform-api ) 里,然而Transform API并没有想象的那么简单好用,翻遍Google终于找到一个兼容Gradle ` 1.5.0 ` 以上的分包插件[ DexKnifePlugin] ( https://github.com/ceabie/DexKnifePlugin ) 。
46
+ 扩展 =>这篇[ Android 热修复使用Gradle Plugin1.5改造Nuwa插件] ( http://blog.csdn.net/sbsujjbcy/article/details/50839263 ) 比较好的介绍了Transform API的使用。
47
47
48
48
###坑4:NoClassDefFoundError ,are you kiding me?
49
49
** 原因:** 通过插件手动指定main dex中要保留的类,虽然分包成功,但是main dex中的类及其直接引用类很难通过手动的方式指定。
50
50
51
51
** 解决方式:**
52
- 看了 [ 美团Android DEX自动拆包及动态加载简介] ( http://tech.meituan.com/mt-android-auto-split-dex.html ) ,他们是通过编写了一个能够自动分析Class依赖的脚本去算出主Dex需要包含的所有必要依赖。看来依赖脚本是跑不掉了 。
52
+ [ 美团Android DEX自动拆包及动态加载简介] ( http://tech.meituan.com/mt-android-auto-split-dex.html ) ,他们是通过编写了一个能够自动分析Class依赖的脚本去算出主Dex需要包含的所有必要依赖。看来写脚本是跑不掉了 。
53
53
54
54
###坑5:自定义脚本 ,read the fuck source!
55
- ** 问题一:** 放进主Dex里应该有哪些类,规则是什么 ?
56
- 查看sdk\build-tools\platform-version\mainDexClasses.rules发现应该放进主Dex类有Instrumentation ,Application,Activity,Service,ContentProvider,BroadcastReceiver,BackupAgent的所有子类。
55
+ ** 问题一:** 哪些类是需要放入主Dex中 ?
56
+ 查看sdk\build-tools\platform-version\mainDexClasses.rules发现放入主Dex相关类有Instrumentation ,Application,Activity,Service,ContentProvider,BroadcastReceiver,BackupAgent的所有子类。
57
57
58
- ** 问题二:** gradle是在哪里计算出主Dex依赖 ?
58
+ ** 问题二:** gradle是在哪里算出主Dex依赖 ?
59
59
查看Gradle编译任务发现有如下3个编译任务:
60
60
<img src =" png/2.png " height = " 100 " width =" 400 " >
61
61
62
- 运行collect任务,发现会在build/multi-dex目录下单独生成manifest_keep.txt文件,该文件其实就是通过上述规则扫描AndroidManifest生成。 manifest_keep.txt保留的是所有需要放入主Dex里的类 。还没完,接下来transformClassesWithMultidexlist任务会根据manifest_keep.txt生成必要依赖列表maindexlist .txt,这里面所有类才是真正放入主Dex里的。bingo,思路已经非常清晰,我们只需要控制manifest_keep.txt的类,依赖关系由系统帮我们生成,即可控制主Dex大小和方法数,安全可靠 !
62
+ 运行collect任务,发现会在build/multi-dex目录下单独生成 ` manifest_keep.txt ` 文件,该文件其实就是通过上述规则扫描 ` AndroidManifest ` 生成。 ` manifest_keep.txt ` 保留的是所有需要放入主Dex里的类 。还没完,接下来 ` transformClassesWithMultidexlist ` 任务会根据 ` manifest_keep.txt ` 生成必要依赖列表 ` maindexlist .txt` ,这里面所有类才是真正放入主Dex里的。bingo,现在非常清楚,我们只需要控制进入manifest_keep.txt中的类即可,最终其类的依赖关系由系统帮我们生成即可,安全绿色可靠 !
63
63
64
64
<img src =" png/3.png " height = " 200 " width =" 500 " >
65
65
<img src =" png/4.png " height = " 200 " width =" 500 " >
66
66
67
- ** 问题三:** 在哪里控制maindexlist.txt的大小?
68
- 由问题一我们知道生成manifest_keep.txt的规则,对于绝大部分工程来说,manifest_keep.txt中80%是Activity,其实我们只需要在主Dex中保留首页 Activity、Laucher Activity 、欢迎页的 Activity 等启动时必要的Activity就OK了。
69
-
67
+ ** 问题三:** 在哪里控制` maindexlist.txt ` 的大小?
68
+ 由问题一我们知道生成` manifest_keep.txt ` 的规则,对于绝大部分工程来说,` manifest_keep.txt ` 中80%是Activity,其实我们并不需要把全部的Activity放入主Dex,只需要保留必要的Activity即可,如首页 Activity、Laucher Activity 、欢迎页的 Activity 等启动时必要的Activity就OK了。
70
69
71
70
下图是Gradle的工作流程:
72
71
<img src =" png/1.png " width =" 800 " >
73
72
来源:[ 深入理解Android之Gradle] ( http://blog.csdn.net/innost/article/details/48228651 )
74
73
75
- 我们只需要在完成任务向量图之后,执行任务之前Hook一下collect任务,做下activity过滤就OK了, 添加Gradle:
74
+ 我们只需要在完成任务向量图之后,执行任务之前Hook一下collect任务,过滤掉不必要的activity就OK了。 添加Gradle:
76
75
```
77
76
//需要加入主dex的Activity列表
78
77
def mainDexListActivity = ['WelcomeActivity', 'MainFunctionActivity']
@@ -97,11 +96,11 @@ afterEvaluate {
97
96
```
98
97
99
98
###坑6:主dex依然爆表,shit again!
100
- 其实上面那段脚本已经成功筛选出我们想要的主Dex的manifest_keep和maindexlist,只是不知道为什么还是把所有类打进主Dex 。这个时候就需要跟[ DexKnifePlugin] ( https://github.com/ceabie/DexKnifePlugin ) 插件配合使用,首先在gradle中加上上述脚本,然后使用插件时在配置文件里加上 ` -split **.** ` 和` #-donot-use-suggest `
99
+ 其实上面那段脚本已经成功筛选出我们想要放入主Dex的 ` manifest_keep列表 ` 和 ` maindexlist列表 ` ,但是在打包的时候还是把所有类打进主Dex(已无语) 。这个时候就需要跟[ DexKnifePlugin] ( https://github.com/ceabie/DexKnifePlugin ) 插件配合使用,首先在gradle中加上上述脚本,然后使用插件时在配置文件中加上 ` -split **.** ` 和` #-donot-use-suggest ` 。DexKnifePlugin插件运行原理很简单,在生成Dex任务之前首先读取自己的配置文件(同时附加上我们前面通过Gradle脚本生成的 ` maindexlist ` ),然后扫描combined.jar(包含工程中所有.class文件)匹配出我们自定义的maindexlist.txt,再替换掉build/multi-dex/maindexlist.txt,和build实例。这样分包的时候就会基于我们的规则生成主Dex。
101
100
102
101
###Congratulation
103
102
恭喜,填坑终于结束,不过还有点不爽的是需要同时维护Gradle脚本和插件的配置。
104
- 于是就将Gradle脚本整合进了插件,以后只要维护一个配置文件就行了。由于带有点业务特性,于是就单独开了个项目,读者可以根据自己需求自己选择。以下是整合插件的配置。
103
+ 于是乎就将Gradle脚本整合进了插件,这样只需维护一个配置文件就行了。读者可以根据自己需求自行选择分开配置还是整合配置。通过这种方式我们把主Dex的方法数维持在15000左右,从此再也不用担心方法数问题了!!!
105
104
106
105
##配置部分
107
106
** 第一步:将repo目录复制到项目根目录**
@@ -111,8 +110,8 @@ afterEvaluate {
111
110
buildscript {
112
111
repositories {
113
112
maven {
114
- url uri('repo')
115
- }
113
+ url uri('repo')
114
+ }
116
115
}
117
116
118
117
dependencies {
0 commit comments