组件化简介
组件化思想是对模块化的进一步演变,相对与模块化,组件化更加灵活,可以在application与library之间相互转换!无论是组件化还是模块化,都是对大型项目的一种耦合度的解耦,方便团队协作开发!
上面是组件化的基本架构图,可以看到组件化一个很明显的特点就是分层!还有一个难点就是组件间的通信。架构图从下到上依次为基础层、组件层和应用层!
基础层主要包含一些基础库如图片加载框架、网络框架等;组件层就是从项目业务中拆分出来的相对独立的业务模块;应用层就是一个“app壳工程”,内部没有实质的业务实现,负责管理和组装其他组件!
实现组件化需要考虑以下问题:
- 组件拆分,即怎么对代码进行拆分
- 组件单独运行,即每一个组件可以作为application单独运行,也可以作为项目的一个library.
- 通信及页面跳转,即各个组件之间怎么进行数据传递及UI调用
- 组件的生命周期,即动态的管理组件的数据变动及视图加载
- 集成调试,即怎么高效的进行编译调试
组件拆分
前面已经介绍了组件化的基本架构图,组件拆分也就有了目标,即将不同的业务模块,拆分到独立的module中,将基础库及各个组件公用的模块拆分到一个基础模块common里,最后在app主工程里进行组装!
组件单独运行
这个问题用代码表示就是apply plugin: 'com.android.library'
与apply plugin: 'com.android.application'
之间的切换,一般是在module下创建一个 gradle.properties 文件,在里面定义一个boolean值isRunAlone来标记该module是否需要独立运行,然后在build.gradle里做如下变动:
if(isRunAlone.toBoolean()){
apply plugin: 'com.android.application'
}else{
apply plugin: 'com.android.library'
}
同时每个组件一般都会增加一个资源前缀resourcePrefix “xxx_”,以防止名称重复。同时对包名和AndroidMenifest进行重新设定:
...
resourcePrefix "module1_"
if (isRunAlone.toBoolean()){
applicationId "com.android.alone"
}
sourceSets{
main{
if (isRunAlone.toBoolean()){
manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
}else {
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
组件的声明周期
由于我们要动态管理组件,所以要给各个组件添加声明周期。为此我们给每个组件增加一个ModuleApplication抽象类,里面定义init等方法,然后在主项目的Application类中,调用各个组件的init方法
public abstract class BaseApp extends Application {
public abstract void init(Application application);
}
组件通信及页面跳转
组件之间不能直接项目引用,要实现通信就只能面向接口编程,接口和实现是完全分离的,这样就可以做到解耦。因为这个接口可能要被多个组件使用,所以接口需要定义在基础层,可以建立一个单独的依赖库,里面定义各个组件对外提供的接口。这时如果要使用某个组件的功能,只需要在依赖库中请求这个接口的实现就行,同时要想每个组件都能获取到这个接口,就需要它在app启动的时候完成注册。
如支付组件要实现支付,首先要先知道登录组件是否登录成功。这时登录组件需要定义一个接口来判断是否登录。可以添加一个 ComponentBase 组件被各个组件依赖,或者直接被基础库组件依赖,在里面定义支付组件可以对外暴露登录状态的Service,同时ComponentBase还提供了一个 ServiceFactory,每个组件中都要提供一个类实现自己对应的 Service 中的抽象方法。在组件加载后,需要创建一个实现类的对象,然后将实现了 Service 的类的对象添加到 ServiceFactory 中。这样在不同组件交互时就可以通过 ServiceFactory 获取想要调用的组件的接口实现,然后调用其中的特定方法就可以实现组件间的数据传递与方法调用。
页面跳转使用aRouter开源库!
集成调试
为了提高效率,我们可以按需将特定的组件集成到app里面:
implementation project (':common')
runtimeOnly project(':login')
runtimeOnly project(':apy')
解决了以上几个问题,组件化的主要的问题就解决了。后面会一步步从零开始手写一个组件化demo 解决更多的细节问题!
参考
Android彻底组件化方案实践
android学习之组件化架构
Android组件化方案
Android组件化之终极方案