Android 项目组件化实践(入门)笔记

在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中的语言切换。

interfaces.jpg

抽取/复用通用的 infrastructure libraries

包括 DownloaderNetworkMonitorStorageMonitor,出于性能因素,复用 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 等。

改造后的模块结构图

comp.png

利用WMRouter 解耦Service的定义与实现

按上图将各个通用的Service 接口定义在BaseComponent中,而实现可以放在上层的Component 或独立的模块。在其它模块中可以经由ServiceManager 通过统一的 Router.getService(XService.class) 调用方式,查找并使用对应的服务。

TODO

  • 新增功能可配置化

P.S. 组件图是由在线绘图工具 diagrams 绘制。

你可能感兴趣的:(Android 项目组件化实践(入门)笔记)