多项目多模块组合之——能聚能散
soapgu opened this issue · comments
-
为什么需要多项目组合?
关于这个问题,也是到最近才真正定型拍板使用多项目的。
- IoC的组件耦合方式限制
Hilt框架用下来还是很好用的,通过注解生成就会自动生成代码装载。而且基本在编译阶段就可以定位装配错误,简单方便。当然成也萧何败也萧何。和我们WPF里面用的IoC框架MEF不同,MEF的加载是模块动态热加载,更多基于反射原理。而Hilt不行,他的加载是静态加载,编译时决定。
所有的耦合都被注入到app的模块中去了
@Component(
modules = {
AppModule.class,
ActivityRetainedCBuilderModule.class,
ServiceCBuilderModule.class,
ApplicationContextModule.class,
BasicModule.class,
LauncherModule.class,
LightModule.class,
OAuthModule.class,
SpaceModule.class,
VersionModule.class
}
)
@Singleton
public abstract static class SingletonC implements App_GeneratedInjector,
BootReceiver_GeneratedInjector,
HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,
ServiceComponentManager.ServiceComponentBuilderEntryPoint,
SingletonComponent,
GeneratedComponent {
}
这是全局的
@Subcomponent(
modules = {
ActivityCBuilderModule.class,
ViewModelCBuilderModule.class,
FootBarViewModel_HiltModules.KeyModule.class,
GB25ViewModel_HiltModules.KeyModule.class,
HiltWrapper_ActivityRetainedComponentManager_LifecycleModule.class,
MainViewModel_HiltModules.KeyModule.class
}
)
@ActivityRetainedScoped
public abstract static class ActivityRetainedC implements ActivityRetainedComponent,
ActivityComponentManager.ActivityComponentBuilderEntryPoint,
HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedLifecycleEntryPoint,
GeneratedComponent {
@Subcomponent.Builder
abstract interface Builder extends ActivityRetainedComponentBuilder {
}
}
这是ViewModel层的
private App injectApp2(App instance) {
App_MembersInjector.injectLauncherManager(instance, iLauncherManager());
return instance;
}
private BootReceiver injectBootReceiver2(BootReceiver instance) {
BootReceiver_MembersInjector.injectActionFactory(instance, optionalOfIMainActivityActionProvider());
return instance;
}
各种注入实现
这样注定了,我必须不同的项目都要配置不同的dependency。build.gradle不能公用
- 不同的项目注定有不同的applicationid,不同的图标,不同的权限等等等。
总之项目的分离比和在一块好。要因地制宜,不能再用WPF那套老**了
-
散:项目分离
明确了项目拆分的目标我们开始动手
我们把项目专门收纳到项目目录
- 每个项目的根目录也是gradle的项目根目录,可以独立编译
- 每个项目的app模块也是这个项目私有
好了解决了项目的独立性问题。接下来我们要怎么解决聚的问题那?
比如项目A,我要模块 A、B、C、D
项目B, 我要模块 A、B、C、E
如何组织协调。
-
聚:项目拼装
在WPF的世界我们有VisualStudio,它有slu文件,他帮我们把模块整合到一个项目里面,那在Android Studio及Gradle的世界里,有没有等价的东西那?
有!
settings.gradle
一个不起眼的配置文件
rootProject.name = "ShgbitGate"
include ':app'
include ':core'
project(':core').projectDir = new File('../../require/core')
include ':shellui'
project(':shellui').projectDir = new File('../../require/shellui')
include ':launcher'
project(':launcher').projectDir = new File('../../require/launcher')
include ':basic'
project(':basic').projectDir = new File('../../require/basic')
include ':oauth'
project(':oauth').projectDir = new File('../../require/oauth')
include ':utility'
project(':utility').projectDir = new File('../../require/utility')
include ':ts310light'
project(':ts310light').projectDir = new File('../../require/ts310light')
include ':version'
project(':version').projectDir = new File('../../require/version')
include ':arcsoft'
project(':arcsoft').projectDir = new File('../../optional/arcsoft')
include ':gb25'
project(':gb25').projectDir = new File('../../optional/gb25')
include 命名耦合模块名
默认模块目录就是Project的子目录。
如果模块是一块“飞地”怎么处理?
project(':name').projectDir = new File('path') 定义相对位置。
然后再bulid.gradle中定义项目依赖就完全不用考虑项目的相对路径
implementation project(path: ':launcher')
implementation project(path: ':basic')
implementation project(path: ':oauth')
目前对gradle这个项目打包工具还不是很熟悉,只能用一点学一点。
相关链接
在Android Studio及Gradle的帮助下总算实现了Android项目模块间耦合的能聚能散
-
散:项目之间图标独立,命名独立,功能独立。各个模块低耦合,保持独立性。
-
聚:模块耦合迅速,接口标准简单,无需过多集成并为之写过多集成代码。
其实开发软件其实有时候和打仗一样。兵无常形水无常势,太多的套路必定束缚开发人员的创造力活力。军队的战斗力不是完全体现在武器上,同样程序的优劣也不是完全体现在语言和框架上。随着功能演化,必然是模块会越分越细,各个模块的耦合会进一步面临挑战。同样军队的兵种分类也是越来越细,多兵种配合合成也同样是军事未来方向。怎么让自己的程序以什么样子的形式组织起来永远没一个完全标准的答案。也许合适的才是最好的吧。