Skip to content

Commit a4b4285

Browse files
author
tangxiaolv
committed
更新Readme
1 parent 22d08b9 commit a4b4285

File tree

7 files changed

+134
-18
lines changed

7 files changed

+134
-18
lines changed

DexKnifePlugin/app/dexknife.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
# 这条配置可以指定这个包下类在第二及其他dex中.
1414
#android.support.v?.**
15-
#将全部类移除主Dex
15+
#将全部类移出主Dex
1616
-split **.**
1717

1818
# 不包含Android gradle 插件自动生成的miandex列表.(不用系统自带分包策略)

DexKnifePlugin/app/maindexlist.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
rx/annotations/Beta.class
2+
rx/annotations/Experimental.class
13
rx/android/concurrency/AndroidSchedulers.class
24
rx/android/concurrency/HandlerThreadScheduler.class
35
android/support/annotation/StyleableRes.class
@@ -25,8 +27,6 @@ android/support/annotation/LayoutRes.class
2527
android/support/annotation/IdRes.class
2628
android/support/annotation/StringDef.class
2729
android/support/annotation/ColorRes.class
28-
rx/annotations/Beta.class
29-
rx/annotations/Experimental.class
3030
android/support/multidex/MultiDex$V14.class
3131
android/support/multidex/MultiDex$V19.class
3232
android/support/multidex/MultiDex$V4.class

DexKnifePlugin/gradle-dexknife-plugin/src/main/groovy/com/ceabie/dexknife/DexKnifePlugin.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ public class DexKnifePlugin implements Plugin<Project> {
3636
componentName.endsWith("${it}")
3737
}
3838
def bool = result != null;
39-
if (!bool) {
40-
printf "main-dex-filter: skipping ${componentName}\n"
39+
if (bool) {
40+
printf "main-dex-filter: keep ${componentName}\n"
4141
}
4242
return bool
4343
}

README.md

Lines changed: 129 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#Android傻瓜式分包插件
2-
注1:不想看前半部分的话可以直接跳过到最下面配置部分。
2+
注1:不想看前半部分的话可以直接跳过到最下面配置部分。
33
注2:本插件是基于[DexKnifePlugin 1.5.2](https://github.com/ceabie/DexKnifePlugin)优化改造而来,感谢ceabie的无私奉献。
44

5-
##填坑之路
6-
`坑1:65536 ,So easy! `
7-
*原因:*Dalvik 的 invoke-kind 指令集中,method reference index 只留了 16 bits,最多能引用 65535 个方法。
8-
参考=>[由Android 65K方法数限制引发的思考](http://jayfeng.com/2016/03/10/%E7%94%B1Android-65K%E6%96%B9%E6%B3%95%E6%95%B0%E9%99%90%E5%88%B6%E5%BC%95%E5%8F%91%E7%9A%84%E6%80%9D%E8%80%83/).
9-
*解决:*
5+
##填坑之路
6+
`坑1:65536 ,So easy! `
7+
*原因:*Dalvik 的 invoke-kind 指令集中,method reference index 只留了 16 bits,最多能引用 65535 个方法。
8+
参考=>[由Android 65K方法数限制引发的思考](http://jayfeng.com/2016/03/10/%E7%94%B1Android-65K%E6%96%B9%E6%B3%95%E6%95%B0%E9%99%90%E5%88%B6%E5%BC%95%E5%8F%91%E7%9A%84%E6%80%9D%E8%80%83/).
9+
10+
*解决:*
1011
```
1112
dependencies {
1213
compile 'com.android.support:MultiDex:1.0.1'
@@ -21,8 +22,9 @@ protected void attachBaseContext(Context base) {
2122
}
2223
```
2324

24-
`坑2:Too many classes in –main-dex-list ,what?`
25-
*原因:*通过上面的官方分包,已经把原Dex分为1主Dex加多从Dex,主Dex保留4大组件,Application,Annotation,multidex等及其必要的直接依赖。由于我们方法数已达到16W之巨,上百个Activity,所以成功的把主Dex又撑爆了。
25+
`坑2:Too many classes in –main-dex-list ,what?`
26+
*原因:*通过上面的官方分包,已经把原Dex分为1主Dex加多从Dex,主Dex保留4大组件,Application,Annotation,multidex等及其必要的直接依赖。由于我们方法数已达到16W之巨,上百个Activity,所以成功的把主Dex又撑爆了。
27+
2628
*解决:*
2729
gradle
2830
```
@@ -39,19 +41,133 @@ afterEvaluate {
3941
```
4042
参考=>[Android Dex分包之旅](http://yydcdut.com/2016/03/20/split-dex/index.html)
4143

42-
`坑3:gradle 1.5.0之后不支持这种写法 ,what the fuck?`
44+
`坑3:gradle 1.5.0之后不支持这种写法 ,what the fuck?`
4345
*原因:*官方解释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)
4446
参考=>这篇[Android 热修复使用Gradle Plugin1.5改造Nuwa插件](http://blog.csdn.net/sbsujjbcy/article/details/50839263)比较好的介绍了Transform API的使用。
4547

46-
`坑4:NoClassDefFoundError ,are you kiding me?`
47-
*原因:*通过插件手动指定main dex中要保留的类,虽然分包成功,但是main dex中的类及其直接引用类很难通过手动的方式指定。
48+
`坑4:NoClassDefFoundError ,are you kiding me?`
49+
*原因:*通过插件手动指定main dex中要保留的类,虽然分包成功,但是main dex中的类及其直接引用类很难通过手动的方式指定。
50+
4851
*解决方式:*
4952
看了[美团Android DEX自动拆包及动态加载简介](http://tech.meituan.com/mt-android-auto-split-dex.html),他们是通过编写了一个能够自动分析Class依赖的脚本去算出主Dex需要包含的所有必要依赖。看来依赖脚本是跑不掉了。
5053

5154
`坑5:自定义脚本 ,read the fuck source!`
52-
插件的工作流程:
55+
问题一:放进主Dex里应该有哪些类,规则是什么?
56+
查看sdk\build-tools\platform-version\mainDexClasses.rules发现应该放进主Dex类有Instrumentation,Application,Activity,Service,ContentProvider,BroadcastReceiver,BackupAgent的所有子类。
57+
58+
问题二:gradle是在哪里计算出主Dex依赖?
59+
查看Gradle编译任务发现有如下3个编译任务:
60+
<img src="png/2.png" width="800">
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大小和方法数,安全可靠!
5363

64+
<img src="png/3.png" width="800">
65+
<img src="png/4.png" width="800">
5466

67+
问题三:在哪里控制maindexlist.txt的大小?
68+
由问题一我们知道生成manifest_keep.txt的规则,对于绝大部分工程来说,manifest_keep.txt中80%是Activity,其实我们只需要在主Dex中保留首页 Activity、Laucher Activity 、欢迎页的 Activity 等启动时必要的Activity就OK了。
69+
70+
71+
下图是Gradle的工作流程:
72+
<img src="png/1.png" width="800">
73+
来源:[深入理解Android之Gradle](http://blog.csdn.net/innost/article/details/48228651)
74+
75+
我们只需要在完成任务向量图之后,执行任务之前Hook一下collect任务,做下activity过滤就OK了,添加Gradle:
76+
```
77+
//需要加入主dex的Activity列表
78+
def mainDexListActivity = ['WelcomeActivity', 'MainFunctionActivity']
79+
afterEvaluate {
80+
project.tasks.each { task ->
81+
if (task.name.startsWith('collect') && task.name.endsWith('MultiDexComponents')) {
82+
println "main-dex-filter: found task $task.name"
83+
task.filter { name, attrs ->
84+
String componentName = attrs.get('android:name')
85+
if ('activity'.equals(name)) {
86+
def result = mainDexListActivity.find {
87+
componentName.endsWith("${it}")
88+
}
89+
return result != null
90+
} else {
91+
return true
92+
}
93+
}
94+
}
95+
}
96+
}
97+
```
98+
99+
`坑6:主dex依然爆表,shit again!`
100+
其实上面那段脚本已经成功筛选出我们想要的主Dex的manifest_keep和maindexlist,只是不知道为什么还是把所有类打进主Dex。这个时候就需要跟[DexKnifePlugin](https://github.com/ceabie/DexKnifePlugin)插件配合使用,首先在gradle中加上上述脚本,然后使用插件时在配置文件里加上`-split **.**``#-donot-use-suggest`
101+
102+
###Congratulation
103+
恭喜,填坑终于结束,不过还有点不爽的是需要同时维护Gradle脚本和插件的配置。
104+
于是就将Gradle脚本整合进了插件,以后只要维护一个配置文件就行了。由于带有点业务特性,于是就单独开了个项目,读者可以根据自己需求自己选择。以下是整合插件的配置。
55105

56106
##配置部分
57-
`第一步:`
107+
`第一步:将repo目录复制到项目根目录`
108+
109+
`第二步:添加根目录Gradle`
110+
```
111+
buildscript {
112+
repositories {
113+
maven {
114+
url uri('repo')
115+
}
116+
}
117+
118+
dependencies {
119+
classpath 'com.ceabie.dextools:gradle-dexknife-plugin:2.0.0'
120+
}
121+
}
122+
123+
```
124+
`第三步:在你的App模块的build.gradle添加插件`
125+
```
126+
apply plugin: 'com.ceabie.dexnkife'
127+
```
128+
129+
`第四步:在你的App模块目录下新建dexknife.txt,并自定义配置`
130+
```
131+
#为注释符
132+
133+
#-----------主Dex中必要依赖的脚本配置-----------
134+
#默认保留四大组件中其他三大组件,Activity组件选择性保留(使用-just activity 选项),若为空默认保留所有Activity
135+
-just activity com.ceabie.demo.MainActivity
136+
137+
#-----------附加类-----------
138+
# 如果你想要某个包路径在maindex中,则使用 -keep 选项,即使他已经在分包的路径中.若为空,默认保留所有
139+
140+
# 保留单个类.
141+
#-keep android.support.v7.app.AppCompatDialogFragment.class
142+
143+
# 这条配置可以指定这个包下类在第二及其他dex中.
144+
#android.support.v?.**
145+
#将全部类移出主Dex
146+
-split **.**
147+
148+
# 不包含Android gradle 插件自动生成的miandex列表.(不用系统自带分包策略)
149+
#-donot-use-suggest
150+
151+
# 不进行dex分包, 直到 dex 的id数量超过 65536.(设置自动执行分包策略)
152+
#-auto-maindex
153+
154+
# 显示miandex的日志.
155+
#-log-mainlist
156+
157+
```
158+
159+
`第五步:在 defaultConfig 或者 buildTypes中打开 multiDexEnabled true,否则不起作用`
160+
161+
##报错
162+
163+
错误1:
164+
```
165+
Error:Execution failed for task ':Toon:transformClassesWithDexForDebug'.> java.lang.NullPointerException (no error message)
166+
```
167+
发生此错误只要切换一次Gradle版本就OK了,比如1.5.0
168+
169+
错误2:
170+
```
171+
Unsupported major.minor version 52.0
172+
```
173+
将JDK升级到1.8

png/2.png

12.8 KB
Loading

png/3.png

12.1 KB
Loading

png/4.png

43.4 KB
Loading

0 commit comments

Comments
 (0)