定义
Android APP组件化架构的目标是告别结构臃肿,让各个业务变得相对独立,业务组件在组件模式下可以独立开发,而在集成模式下又可以变为arr包集成到“app壳工程”中,组成一个完整功能的APP;
从组件化工程模型中可以看到,业务组件之间是独立的,没有关联的,这些业务组件在集成模式下是一个个library,被app壳工程所依赖,组成一个具有完整业务功能的APP应用,但是在组件开发模式下,业务组件又变成了一个个application,它们可以独立开发和调试,由于在组件开发模式下,业务组件们的代码量相比于完整的项目差了很远,因此在运行时可以显著减少编译时间。
这是组件化工程模型下的业务关系,业务之间将不再直接引用和依赖,而是通过“路由”这样一个中转站间接产生联系,而Android中的路由实际就是对URL Scheme的封装。
实施
- 组件模式和集成模式的切换
if (isModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
- 组件模式和集成模式下表单文件的切换
sourceSets {
main {
if (isModule.toBoolean()) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
集成模式下,业务组件的表单是绝对不能拥有自己的 Application 和 launch 的 Activity的,也不能声明APP名称、图标等属性,总之app壳工程有的属性,业务组件都不能有
- 全局application的获取
sourceSets {
main {
if (isModule.toBoolean()) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
//集成开发模式下排除debug文件夹中的所有Java文件
java {
exclude 'debug/**'
}
}
}
}
在组件化工程模型图中,功能组件集合中有一个 Common 组件,Common 有公共、公用、共同的意思,所以这个组件中主要封装了项目中需要的基础功能,并且每一个业务组件都要依赖Common组件,Common 组件就像是万丈高楼的地基,而业务组件就是在 Common 组件这个地基上搭建起来我们的APP的,Common 组件会专门在一个章节中讲解,这里只讲 Common组件中的一个功能,在Common组件中我们封装了项目中用到的各种Base类,这些基类中就有BaseApplication 类;
但是,实际上业务组件中的Application在最终的集成项目中是没有什么实际作用的,组件自己的 Application 仅限于在组件模式下发挥功能,因此我们需要在将项目从组件模式转换到集成模式后将组件自己的Application剔除出我们的项目
- 依赖问题
aar文件不会把相关依赖打包,所以在common组件中定义一个统一的依赖接口 - 组件之间的调用和通信
调用:路由框架
通信:Android广播或第三方事件总线(EventBus) - 组件之间资源名冲突
方案:每个组件资源名一组件名作为前缀
组件化中的项目工程类型
一般为三种类型:壳工程、业务组件、功能组件
壳工程
app壳工程是从名称来解释就是一个空壳工程,没有任何的业务代码,也不能有Activity,但它又必须被单独划分成一个组件,而不能融合到其他组件中功能组件和common组件
功能组件是为了支撑业务组件的某些功能而独立划分出来的组件,功能实质上跟项目中引入的第三方库是一样的
commom组件的独特性:
- Common组件的 AndroidManifest.xml 不是一张空表,这张表中声明了我们 Android应用用到的所有使用权限 uses-permission 和 uses-feature,放到这里是因为在组件开发模式下,所有业务组件就无需在自己的 AndroidManifest.xm 声明自己要用到的权限了
- Common组件的 build.gradle 需要统一依赖业务组件中用到的 第三方依赖库和jar包,例如我们用到的ActivityRouter、Okhttp等等
- Common组件中封装了Android应用的 Base类和网络请求工具、图片加载工具等等,公用的 widget控件也应该放在Common 组件中;业务组件中都用到的数据也应放于Common组件中,例如保存到 SharedPreferences 和 DataBase 中的登陆数据
- Common组件的资源文件中需要放置项目公用的 Drawable、layout、string、dimen、color和style 等等,另外项目中的 Activity 主题必须定义在 Common中,方便和 BaseActivity 配合保持整个Android应用的界面风格统一
- 业务组件和main 组件
业务组件就是根据业务逻辑的不同拆分出来的组件
main组件的特殊性:
Main组件集成模式下的AndroidManifest.xml是跟其他业务组件不一样的,Main组件的表单中声明了我们整个Android应用的launch Activity,这就是Main组件的独特之处;所以我建议SplashActivity、登陆Activity以及主界面都应属于Main组件,也就是说Android应用启动后要调用的页面应置于Main组件
组件化项目混淆方案
组件化项目的Java代码混淆方案采用在集成模式下集中在app壳工程中混淆,各个业务组件不配置混淆文件。集成开发模式下在app壳工程中build.gradle文件的release构建类型中开启混淆属性,其他buildTypes配置方案跟普通项目保持一致,Java混淆配置文件也放置在app壳工程中,各个业务组件的混淆配置规则都应该在app壳工程中的混淆配置文件中添加和修改。
之所以不采用在每个业务组件中开启混淆的方案,是因为 组件在集成模式下都被 Gradle 构建成了 release 类型的arr包,一旦业务组件的代码被混淆,而这时候代码中又出现了bug,将很难根据日志找出导致bug的原因;另外每个业务组件中都保留一份混淆配置文件非常不便于修改和管理,这也是不推荐在业务组件的 build.gradle 文件中配置 buildTypes (构建类型)的原因
工程的build.gradle文件和gradle.properties文件
- 在组件化项目中因为每个组件的 build.gradle 都需要配置 compileSdkVersion、buildToolsVersion和defaultConfig 等的版本号,而且每个组件都需要用到 annotationProcessor,为了能够使组件化项目中的所有组件的 build.gradle 中的这些配置都能保持统一,并且也是为了方便修改版本号,我们统一在Android工程根目录下的build.gradle中定义这些版本号,当然为了方便管理Common组件中的第三方开源库的版本号,最好也在这里定义这些开源库的版本号,然后在各个组件的build.gradle中引用Android工程根目录下的build.gradle定义的版本号
- 在组件化实施流程中我们了解到gradle.properties有两个属性对我们非常有用:
- 在Android项目中的任何一个build.gradle文件中都可以把gradle.properties中的常量读取出来,不管这个build.gradle是组件的还是整个项目工程的build.gradle;
- gradle.properties中的数据类型都是String类型,使用其他数据类型需要自行转换;
页面跳转方案
管理组件
上传到maven或jcenter仓库上供我们引用