前言
项目越做越大,每次编译的时间越来越长,体验特别不好,在加上协同开发的时候,项目管理问题,因此开始了我的Android项目的模块化开发之旅。
1.模块化开发的优势
- 单独模块开发,编译迅速,调试方便
- 模块之间相互解耦,协同开发不容易出错
- 实际使用后,项目打包后的体积也小了很多
2.遇到的问题和解决方案
- 模块之间的数据传递
- 模块管理
- Android Studio中gradle.properties文件中进行配置,是否加载模块进入项目工程,不需要的时候不加载进来可以加快工程的编译速度
- 版本问题使用nexus进行控制,模块采取arr或者本地Modle进行加载进主工程。同样配置在gradle.properties中
- 架包问题采用配置公共版本号,配置在整体项目的build.gradle文件中,与项目工程配置区分开
- 资源冲突
- 资源文件严格按照命名规则,添加模块名字的前缀,可用gradle进行强制检测,未实践。
3.项目工程需要的配置
- gradle.properties 文件
- nexus私服配置
- 本地环境配置
- 模块化开关
- 模块版本配置
- 工程的build.gradle文件
- 项目架包版本统一管理
- 模块的buile.gradle文件
- nexus私服上传配置
- 模块内部代码资源目录配置
4.项目工程结构及配置
- 能转化成app的modle(上层模块)

权限模块主要做整个app的欢迎和登录注册等功能,不管生产还是开发的时候都拥有Launcher界面,所以在src/main/java/debug中没有一个DebugLoginActivity作为模块的Launcher界面,其他的modle需要一个DebugLoginActivity作为他的启动界面,里面一般做自动登录的功能,然后直接跳转到目标界面,空出一个回调方法用来跳转到下一个界面,开发的时候直接跳转到正在调试的界面。打包的时候debug目录不会打进去。模块内部代码资源目录配置:
1 | sourceSets { |
模块application和library转换:
1 | if (isModule.toBoolean()) { |
控制开关配置在gradle.properties中:
1 | # isModule = false 是否模块开发 |
发布及版本控制配置在gradle.properties文件中:
1 | authRelease=false |
- 不能转化成的app的modle(组件)
- 防止循环依赖项目需要一个核心组件,上层模块统一只依赖核心组件core
- 核心组件依赖其他基本组件,不如联网组件,数据库组件等。。。
- 核心组件中添加整个项目所需要的架包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
testCompile 'junit:junit:4.12'
debugCompile "com.squareup.leakcanary:leakcanary-android:$rootProject.leakcanaryVersion"
releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:$rootProject.leakcanaryVersion"
testCompile "com.squareup.leakcanary:leakcanary-android-no-op:$rootProject.leakcanaryVersion"
compile "com.android.support:appcompat-v7:${SUPPORT_LIB_VERSION}"
compile "com.android.support:recyclerview-v7:${SUPPORT_LIB_VERSION}"
compile "com.android.support:cardview-v7:${SUPPORT_LIB_VERSION}"
compile "com.android.support:design:${SUPPORT_LIB_VERSION}"
compile "com.android.support.constraint:constraint-layout:${CONSTRAINT_LAYOUT}"
compile "com.android.support:multidex:$rootProject.multidexVersion"
compile "com.alibaba:arouter-api:$rootProject.arouterApiVersion"
annotationProcessor "com.alibaba:arouter-compiler:$rootProject.arouterCompilerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$rootProject.daggerCompilerVersion"
annotationProcessor "com.google.dagger:dagger-android-processor:$rootProject.daggerAndroidProcessorVersion"
compile "com.orhanobut:logger:$rootProject.loggerVersion"
compile "com.google.dagger:dagger:$rootProject.daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$rootProject.daggerCompilerVersion"
compile "com.google.dagger:dagger-android:$rootProject.daggerAndroidVersion"
compile "com.google.dagger:dagger-android-support:$rootProject.daggerAndroidSupportVersion"
annotationProcessor "com.google.dagger:dagger-android-processor:$rootProject.daggerAndroidProcessorVersion"
compile "io.reactivex.rxjava2:rxjava:$rootProject.rxjava2Version"
compile "io.reactivex.rxjava2:rxandroid:$rootProject.rxandroid2Version"
compile "com.jakewharton.rxbinding2:rxbinding:$rootProject.rxbinding2Version"
compile "com.jakewharton.rxbinding2:rxbinding-support-v4:$rootProject.rxbinding2SupportV4Version"
compile "com.jakewharton.rxbinding2:rxbinding-appcompat-v7:$rootProject.rxbinding2AppcompatV7Version"
compile "com.jakewharton.rxbinding2:rxbinding-design:$rootProject.rxbinding2DesignVersion"
compile "com.jakewharton.rxbinding2:rxbinding-recyclerview-v7:$rootProject.rxbinding2recyclerviewV7Version"
compile "com.jakewharton.rxrelay2:rxrelay:$rootProject.rxrelay2Version"
compile "com.trello.rxlifecycle2:rxlifecycle:$rootProject.rxlifecycle2Version"
compile "com.trello.rxlifecycle2:rxlifecycle-android:$rootProject.rxlifecycle2AndroidVersion"
compile "com.trello.rxlifecycle2:rxlifecycle-components:$rootProject.rxlifecycle2ComponentsVersion"
compile "com.tbruyelle.rxpermissions2:rxpermissions:$rootProject.rxpermissions2Version"
compile "com.blankj:utilcode:$rootProject.utilcodeVersion"
compile "me.yokeyword:fragmentation:$rootProject.fragmentationVersion"
compile "me.yokeyword:fragmentation-swipeback:$rootProject.fragmentationSwipebackVersion"
if (httpRelease.toBoolean()) {
compile "com.gavel:http:$HTTP_VERSION_NAME"
} else {
compile project(':http')
}
if (dbRelease.toBoolean()) {
compile "com.gavel:db:$DB_VERSION_NAME"
} else {
compile project(':db')
}
if (basicRelease.toBoolean()) {
compile "com.gavel:basic:$BASIC_VERSION_NAME"
} else {
compile project(':basic')
}
}
架包版本配置在整个项目的build.gradle中。
1 | // 项目架包版本控制 |
发布及版本控制配置在gradle.properties文件中:
1 | # 底层lib模块 |
- 打包发布主体app模块依赖
1 | dependencies { |
- 项目工程settings.gradle配置
1 | if (!isModule.toBoolean()) { |
app模块是主体模块,模块化开发的时候不需要加载进项目工程,其他基本模块发布出去后,项目只需要依赖arr文件,进行远程私服依赖,所以也不需要加载进工程以加快编译速度。
5.总结
- 修改gradle.properties中的isModule要能正常切换application和library。基本就算完事了,配置还是比较简单的。
- 模块化难的是对于业务的解耦。一个功能是作为一个基本组件还是作为一个上层模块。功能细分到什么程度都是很讲究的。
- 项目github地址