在2019的9月份,我参与了公司内部将多个app整合成为一个app的项目改造,并负责整个的实施过程。期间碰到一些问题,偶尔有些心得,特记录如下。
直接来看,这 N个项目的共同点在于都有统一的登录流程,之后有各自差异化的初始化流程和对应的feature。另外底层的infrastructure也有共有的部分,如EventBus,网络层组件,下载组件等。最初的设想是将所有现存的app都变为module,然而初期评估下来,核心app部分的改动可能过大,于是围绕它,准备将其它(N-1)个app集成进去。总体上的步骤可分为以下几点:
先统一登录模块,初始化逻辑独立迁移
底层通用业务模块中独立定义 IAuthenticationService
接口,然后在其它模块中实现。使用SPI (Service Provider Interface)
的机制来查找实现,并添加到公共的服务管理类 ServiceManager
中。这一步在Android上可以使用 AutoService
来实现。
建立底层基础模块 (BaseComponent)
Deeplink
对于模块间的deeplink跳转逻辑, 暂时统一定义在此处(后续看来更好的办法,或可以尝试引入ARoute)。App内部语言切换
按IAuthenticationService
相似的实现策略,可以对ILanguageService
也做出相似的实现,以便全局管理app中的语言切换。
抽取/复用通用的 infrastructure libraries
包括 Downloader
,NetworkMonitor
,StorageMonitor
,出于性能因素,复用 4.x
版本以后的 OkHttpClient
等等。
模块化后,编译配置的变更
- 为了防止资源重复,将library中的资源增加前缀(prefix)以防止命名冲突
android {
resourcePrefix 'lib_a_'
// ...
}
- 当编译时出现依赖的dependency重复相关的错误时 ❌ ,可以使用
compileOnly (...)
, 或
implementation(a_lib) {
exclude module: 'duplicate_module'
}
或是自定义多版本冲突后的解决策略:
configurations.all {
resolutionStrategy {
forcedModules = [
"com.google.code.gson:gson:$gsonVersion",
// ...
]
}
}
各个module中 proguard 的声明变化
apply plugin: 'com.android.library'
android {
defaultConfig {
consumerProguardFiles 'your-proguard file'
}
}
【可选】支持单独的module作为独立可运行的app
在module的build.gradle
中更改配置
if (isStandalone()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
以上区分了App 或 library 的配置,还要应用于dependencies
, defaultConfig
, ProguardFiles
等。
改造后的模块结构图
利用WMRouter 解耦Service的定义与实现
按上图将各个通用的Service 接口定义在BaseComponent
中,而实现可以放在上层的Component
或独立的模块。在其它模块中可以经由ServiceManager
通过统一的 Router.getService(XService.class)
调用方式,查找并使用对应的服务。
TODO
- 新增功能可配置化
P.S. 组件图是由在线绘图工具 diagrams 绘制。
💰 赞赏支持
请支持我进行更好地创作 ☕️