首先,谈谈为什么要写这个系列的文章,严格来说是一段学习组件化的笔记。
很多小伙伴都了解组件化,也学习过,但是像我这样没有大型项目经验的,很难深入理解它的意义。直到去年公司开启了新项目,我带着2个小伙伴一起从0开发到1(当然还有产品,测试及后端每个人的功劳),突破百万日活。
随着功能模块越来越多,开发人员交替,开发风格不统一(有的mvp,有mvc,甚至有站撸activity的),工程不仅代码臃肿,目录下多达38个包。功能模块严重耦合,开发中经常引起老功能bug,或者一个bug反复出现(让你不写单元测试)。在被折磨的内心崩溃以后,终于在组件化和单元测试中找到了救赎。(单元测试:请看https://www.jianshu.com/nb/26784460)
吐槽完毕,开撸代码,想看基础的推荐这几篇文章(是不是拿完链接,就可以撤了):
- 开源最佳实践:Android平台页面路由框架ARouter
- 阿里ARouter开源组件化框架项目实践
- Android组件化方案(这篇文章给出了相对完整的组件化方案,剩下的就是自己实战了)
- AndroidStudio本地化配置gradle的buildToolsVersion和gradleBuildTools
目标
首先,我们的目标是告别臃肿,建立一个业务组件之间独立,即可集成开发,也可组件化开发的基础项目框架。
如果是简单的建立几个module,那谁都会,我们的项目里也有很多module。这里要解决的主要问题是:
- 组件既能独立编译开发,也可以集成开发,组件间可以灵活组合打包。
- 组件之间是没有关联的,如何通信,页面如何调用。(这里引入了“路由”的概念,组件间通过路由中转建立联系,Android用的是URL Scheme作为路由)
创建基础工程
app:为壳工程,只负责集成各个module。
lib_common:为公共基础库,引入大部分第三方库和工具类。
module_setting:项目各种开关,功能设置(具体什么module自己选择)
module_main:主module,暂时只有一个MainActivity。

1. 创建config.gradle,对所以组件的gradle配置、第三方依赖,统一管理。(关于本地化配置gradle的教程,参考开头推荐的文章)
ext {//提取依赖,版本号,方便管理
appVersion = [
versionCode: 1,
versionName: "1.0.0"
]
android = [
compileSdkVersion: 26,
minSdkVersion : 18,
targetSdkVersion : 26,
]
dependencies = [
appcompat_v7 : 'com.android.support:appcompat-v7:26.1.0',
constraintLayout : 'com.android.support.constraint:constraint-layout:1.1.1',
support_design : 'com.android.support:design:26.1.0',
support_annotations: 'com.android.support:support-annotations:26.1.0',
testJunit : 'junit:junit:4.12',
textRunner : 'com.android.support.test:runner:1.0.0',
androidTestEspresso: 'com.android.support.test.espresso:espresso-core:3.0.0',
]
}
这里api、implementation、compile的区别需要注意,以免重复引入依赖:
implementation:编译的依赖只作用于当前的module
compile 与 api:二者等同,无区别
dependencies {//module引用config.gradle的配置
implementation fileTree(dir: 'libs', include: ['*.jar'])
api rootProject.ext.dependencies.appcompat_v7
api rootProject.ext.dependencies.support_design
api rootProject.ext.dependencies.constraintLayout
2. 集成模式 和 组件化模式切换
我们需要一个开关,在gradle.properties中创建"isModule"变量,在每个module的build.gradle中,通过它来切换开发模式。
# false表示是集成化开发模式,true表示是组件化开发模式
isModule = true
if (isModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
那么问题来了,组件独立编译时,需要临时的manifest,Application来初始化一些配置。并在集成模式下移除这些配置。以module_main为例:

怎么灵活的切换以上文件呢,还是要用到"isModule",在build.gradle的android{}下,通过判断isModule,加载不同的AndroidManifest.xml,并在集成模式中移除debug文件夹
android {
...
sourceSets {
main {
if (isModule.toBoolean()) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
exclude 'debug/**'
}
}
}
}
3. 公共基础库(lib_common)
作为公共的基础库,除了引入依赖,还具有一下功能:
- 引入了常用的工具类、公共/自定义widget,公共常量
- 第三方框架(数据库,网络,图片,RxJava等)
- permission声明
- 一些公用的资源文件,styles、dimens、colors、drawable等等
4. app壳工程,主要功能
app壳工程,没有任何的业务代码,主要用于集成模式下:
- build.gradle依赖各个组件
- 配置AndroidManifest.xml
- 声明Android应用的Application(继承lib_common的BaseApplication)。
- 配置工程混淆文件
小结:
本章介绍了:为什么要用组件化,需要解决的问题,组件化工程的配置
项目也才搭建到这里,下一章我们会引入阿里的ARouter组件化框架,完善基础工程。