组件化架构图

前言

xx_android 是单一工程模式,所有业务功能都是集中在同一个工程里实现的,业务模块以package方式进行组织。

单一工程

  1. 合代码经常发生冲突。
  2. 代码严重耦合,新人学习成本高,迭代和维护成本大,功能经常发生衰退。
  3. 改了一行代码 或只调了一点UI,就要run整个项目,编译时间效率低。
  4. 多人团队协作效率低效。

组件化介绍

1. 模块化

  1. module与模块基本一个概念,就是原本app模块承载了所有的功能。
  2. 模块化就是拆分成多个模块放在不同的module里面,每个功能代码都在自己所属的module中添加。
  3. 通常情况都会有基础模块module_commom,主要提供baseActivity,baseFragment,http,图片加载等基础能力,然后每个业务模块都会依赖module_commom模块。
  4. 毋庸置疑业务模块之间也需要相互依赖。例如:‘首页’、‘订单’、‘我的’、‘优惠券’、都需要跳转到‘油站详情’的,必须依赖‘油站详情’,而‘油站详情’需要选择优惠券能力,也得需要依赖‘优惠券’。
  5. 那么模块之间的存在复杂的依赖关系。

模块化

模块化 在各个业务功能比较独立的情况下是比较合理的,但多个模块中肯定会有页面跳转、数据传递、方法调用 等情况,所以必然存在以上这种依赖关系,即模块间有着高耦合度。 高耦合度 加上 代码量大,就极易出现上面提到的那些问题了,严重影响了团队的开发效率及质量。

2. 组件化

组件化,去除模块间的耦合,使得每个业务模块可以独立当做App存在,对于其他模块没有直接的依赖关系。 此时业务模块就成为了业务组件。
除了业务组件,还有抽离出来的业务基础组件,是提供给业务组件使用,但不是独立的业务,例如分享组件、广告组件;还有基础组件,即单独的基础功能,与业务无关,例如 图片加载、网络请求等。

组件化

  1. 组件依赖关系上层依赖下层,修改频率是上层高于下层
  2. 基础组件是通用基础能力,修改频率相对于低,作为sdk提供所有的项目集成使用。
  3. common组件,作为支撑业务组件、业务基础服务的基础(BaseActivity/BaseFragment等基础能力),同时依赖所有的功能基础组件,提供多数业务组件需要的基本功能,并且统一了基础组件的版本号。所以业务组件、业务基础服务 所需的基础能力只需要依赖common组件即可获得。
  4. 业务组件、业务基础服务,都依赖common组件。但业务组件之间不存在依赖关系,业务基础服务之间不存在依赖关系。而业务组件 是依赖所需的业务基础组件的,例如几乎所有业务组件都会依赖广告组件 来展示Banner广告、弹窗广告等。
  5. 最上层则是主工程,即所谓的“壳工程”,主要是集成所有的业务组件、提供Application唯一实现、gradle、manifest配置,整合成完备的App

组件开发规范

  • 规范1:资源命名规则

展示项目资源图

  1. 所有的资源文件名称都需要以业务组件名前缀命名,需要注意不能与其他组件前缀冲突,例如业务组件名为:’login’,则相关资源文件命名例子:

    • layout文件:login_activity_main.xml
    • anim文件:login_anmin_hide.xml
    • drawable文件:login_et_bg.xml
    • string文件:login_mobile_input

    还需要在build.gradle文件配置,
    //但是resourcePrefix这个值只能限定xml里面的资源,并不能限定图片资源,所有图片资源仍然需要手动去修改资源名。
    resourcePrefix “login_”

  2. 所有的业务代码文件都需要以业务名称前缀命名,需要注意不能与其他组件业务代码前缀冲突,例如业务组件名称:’order’

    • 订单列表:orderList.kt
    • 订单详情:orderDetail.kt
  • 规范2:组件间通信

    1. 平时开发中我们常用接口进行解耦,对接口的实现不用关心,避免接口调用与业务逻辑实现紧密关联。这里组件间的解耦也是相同的思路,仅依赖和调用服务接口,不会依赖接口的实现

展示暴露服务api

  • 暴露组件,只存放服务接口、服务接口相关的实体类、路由信息、Fragment的获取、便于服务调用uitl等。
  • 服务调用方只依赖服务提供方的报露组件,接口的具体实现由服务方与调用相互协调后,提供工具让调用方直接调用。如home_module依赖login_export,而不是home_module依赖login_module。
  • 组件需要依赖自己暴露的组件,并实现服务接口,如login_module依赖login_cart 并实现其中的服务接口。
  • 接口的实现注入由阿里ARouter路由框架完成,和页面跳转一样使用路由信息。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
buildscript {

repositories {
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
}

allprojects {
repositories {
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}
  • 规范3:数据存储

    1. 使用SharedPreferences和MMKV时,每个业务模块只管理自己模块需要的数据,SharedPreferences文件名需要通过业务前缀来区分,MMKV实例(MMKV.mmkvWithID)需要通过业务前缀来区分,防止不同组件间数据发生冲突
    2. 当某些数据需要全局共享时,可以考虑下沉到底层模块
  • 规范4:组件生命周期分发
1
2
3
task clean(type: Delete) {
delete rootProject.buildDir
}
  • 规范5:开发文档

    1. 每个组件都要维护好说明文档,通常都是一个readme文件。一般包含以下说明:

    2. 组件的功能介绍

    3. 组件功能使用说明

    4. 组件历史版本记录

    5. 注意事项

      尽量做到团队内任何一个成员,通过该文档就能使用组件,而不需要找到组件的开发人员来讲解。