组件化方案的第三种选择

背景:
市面上已开源的或者已发布的组件化方案,多数都是开发阶段单一工程结构,切换module模式。本质上依然没有达到代码完全隔离的目的,开发与整合测试中的一些痛点还是没有彻底解决

我们的方案:代码完全隔离,互相只能依赖,不可编辑,各模块可以单独运行,也可组合依赖

本文内容为亲自实践并验证之后整理,理解了思路,具体实施方案其实可以有多种,最主要的是自己觉得合适的。

先看看常见的方案

第一种方案-单一项目结构

该架构模式比较大众化,很多组件化demo 都是这种结构,比如得到

核心思想:所有业务组件及common组件以module形式存在于一个项目内

优点: 项目没有冗余,便于管理

缺点:没有达到组件完全隔离效果,组件插拔使用仍需新建或导入项目

代码结构

解读:

  • app:项目module,无具体业务,不包含具体页面,只负责编译依赖组件、集成打包
  • module_main: main组件,定义启动页与主页
  • module_a:业务组件
  • moduel_baidulocation:功能组件
  • module_common: 基础公共组件

各组件为独立工程架构后面说明,基本配置及思想不变

组件文件结构 :

由于组件以Module形式存在于项目内

因此只保留Module目录文件,其他工程文件统一由主体工程提供

主体项目配置

setting.gradle配置

include所有组件module

如:

1
2
3
4
include ':app',
':module_main',
':module_a',
':module_common'

app Module配置

build.gradle配置

始终为com.android.application

编译依赖:

  1. 依赖底层公共组件
  2. 集成模式条件下,编译全部组件

如:

1
2
3
4
5
6
if(!isDebug.toBoolean()){
implementation project(':module_main')
implementation project(':module_a')
}

implementation project(':module_common')

调试运行

修改gradle.properties

isDebug=true,独立运行调试

isDebug=false,编译运行整个project

组件单独运行与整个project运行切换:

注意:组件间资源重复会在最终打包时发生冲突,即使通过编译成功打包,在运行时也会出现资源问题。建议增加模块前缀加以区分避免

第二种方案-多项目结构

核心思想:每个组件都做为一个独立项目存在 ,负责组合打包各组件的主项目只有一个

优点: 除公共组件或功能组件存在依赖关系外,组件间互相隔离

缺点:项目冗余

代码结构

解读:

  • ComponentApp为主工程,最终负责打包组件,无具体业务,配置程序相关内容
  • ComponentMain为主组件,配置启动页与首页
  • ComponentA为业务组件
  • ComponentBaidu 为功能组件
  • ComponentCommon 为公共组件

所有组件依赖公共组件

继承BaseApplication, 开发时将全局Application转型为BaseApplication,避免打包时 Application失效

文件结构

  • 具体路径按需存放

  • 各组件均为独立项目

主体项目配置

setting.gradle配置

以依赖项目与主体项目在同级目录为例:

引入依赖组件,使用project (':项目').projectDir = new File('../项目')定义路径

1
2
3
4
5
6
7
8
9
10
11
12
13
include ':app'

include ':ComponentMain'
project (':ComponentMain').projectDir = new File('../ComponentMain')
include ':ComponentMain:main'

include ':ComponentA'
project (':ComponentA').projectDir = new File('../ComponentA')
include ':ComponentA:moduleA'

include ':ComponentCommon'
project (':ComponentCommon').projectDir = new File('../ComponentCommon')
include ':ComponentCommon:common'

build.gradle配置

编译各组件内指定Module

1
2
3
4
5
6
if(!isDebug.toBoolean()){
implementation project(':ComponentMain:main')
implementation project(':ComponentA:moduleA')
}

implementation project(':ComponentCommon:common')

调试运行

修改 gradle.propertiesisDebug

app Module由于没有默认Activity,因此无法运行

注意:有依赖关系的组件 配置需一致,否则编译失败

第三种方案-彻底组件化

核心思想:最大化隔离,最少代码侵入,最少修改感知

方案

  1. 抛弃开发阶段与发布阶段gradle配置的Library与Application切换
  2. 每一个组件都是一个独立的工程,组件仍是Library,与开发阶段使用的demo分离。整体工程一并发布。最终只能有一个Application
  3. 组件互相隔离,互相不可编辑,只能使用。Library 发布为jar或aar文件,远程依赖引入
  4. 清单文件配置(所有我们知道的配置)都可以写进Library,最后打包时会自动合并,无需人为干扰。
  5. gradle扩展配置,manifest 经常变化的配置写进gradle配置文件,减少配置侵入
  6. 业务组件之间依赖后通过路由或其他方式交互(自行选择),功能组件可直接依赖使用

涉及知识点

仓库以maven为例,以下内容,搜索引擎都可解答

  1. Library Maven 配置
  2. 搭建本地Maven仓库
  3. Manifest动态配置替换
  4. Gradle插件开发
  5. 组件交互:Arouter,ActivityRouter

实践

理解以上所有点,一步一个脚印

组件交互方案

仓库发布方式

分类

  • jcenter
  • maven
  • 本地私有仓库
私有仓库搭建

拥抱 Android Studio 之四:Maven 仓库使用与私有仓库搭建
在Android Studio中发布Library到jCenter公共仓库
自建私有Maven 仓库

完结撒花