Android组件化实践

一、为什么要组件化?组件化有哪些好处?

网上提到的组件化的好处有很多,这里我就仅列举几个比较明显的好处。

1.代码隔离,实现被动解耦

情景a 小王想实现一个右上角有“X”号的dialog,但是他发现基础UI库里dialog没有这个按钮,于是小王想偷偷在基础组件库里写一个tag,用于标记dialog是否右上角有“X”号。

(组件化前)小王偷偷写入成功,大家纷纷效仿小王,最后基础库里的dialog一共有十几处tag用于标记状态。后来,UI大改版,大家发现这个dialog代码过于复杂只能重构。
(组件化后)小王发现基础库的代码是远程依赖,自己并没有修改权限,只好作罢。他通过继承的方式,写了一个属于自己模块的dialog。

情景b: 小张是一个邋遢的人,他写代码从不一口气写完。有一天,小张重构了BaseFragment,但是他写了一半,项目无法编译就提交了,而且他还请了十天的假。

(组件化前) 项目组正在紧急修复一个bug,但是发现怎么也无法编译成功。经查,是小张改了BaseFragment,改的异常复杂,大家还不敢修复,然后又联系不到小张。最终导致项目delay了一个星期。
(组件化后) 项目组一直依赖的是maven库的上版release包,base库虽然代码不能编译,但是app并不直接依赖源码。项目正常推进。

情景c: 小李和小王分别在开发两个模块,小李发现小王im聊天类写的非常的出色,所以准备直接引用小王写的类。但是小王准备对该模块进行升级

(组件化前)两人都愉快的开发,直到上线的那天,小李发现自己im消息加载不出来头像,于是他甩锅给小王。后来两人为此闹的不可开交。
(组件化后)im属于基础组件,要求所有暴露在外的接口必须保持不变。小王升级了组件以后,对小李没有任何影响。

2.工程有了层次感,更容易找到自己的“一亩三分地”

情景a:小刘是一个新来的同学,他接到一个需求,说要给视频直播间加一个dialog。

(组件化前)小刘一顿操作,给直播间一个按钮加了一个dialog,但他不知道音频直播间也在用这个模块,后来线上出现了大批崩溃。
(组件化后)小刘通过名字迅速找到了LiveComponent模块,因为AudioLiveComponent是另外一个模块,所以修改了并没有产生影响。

3.组件化后的模块就像摆在货架的商品,其他app也可以快速集成使用

情景a:A公司日益壮大,一个App已经无法满足公司的雄心壮志,A公司决定要写一个新的以直播为导向的app

(组件化前)程序员们开始疯狂从原有的app上复制代码。从基础框架、网络请求、图片加载 到 数据库、原子参数。后来服务端决定对接口进行升级,程序员们又开始一个一个项目的修改代码
(组件化后)程序员只参照文档 一行gradle一个组件,迅速搭建了app架子。服务端进行接口升级后,各app仅仅把自己依赖的版本号进行升级,就完成了整个app网络请求的改造。

二、组件化长什么样子?有哪些规范?

1.组件化一般分为:

App壳:不参杂任何逻辑,只是把各个业务组件整合在一起。
业务组件层:承担业务功能,不可复用,程序员日常迭代的地方。
功能组件层:封装一些基本的功能,包括日志、分享、登录等。一般不进行修改,供上层业务调用。
基础库:非常基础的库,能干的事情较单一,并且不承担任何业务逻辑。

下图以类似“美团app”为例


想象中的美团app架构

注意:图中的依赖关系是自上而下的,同级之间禁止依赖。

2.那组件化的代码又是什么样子呢?以为做的个人app为例

我的项目中有:大厅、直播、彩票等上层模块。接下来是网络请求、基础base架构模块。他的文件结构是这样的


我自己的app文件架构

项目是不是看起来清新又直白。这就是组件化的魅力。

三、利用阿里云效搭建自己的组件库

0.创建一个组件

a:通过Androidstudio可以为我们自动创建一个组件。


第一步:创建module

b:我们一般选择Android library

第二步:创建一个Android Library

c:然后起一个名字,模块名我比较喜欢加Component(为了和基础组件区分),包名则省略这个后缀。

第三步:起名字

d:然后我们重新build一下,新模块就建立好啦,模块有一个三道杠的标示。

第四步:看看我们干的好事
1.进入阿里云效,选择制品仓库,选择maven仓库。

根据提示配置gradle

步骤一:请在build.gradle中设置仓库的访问凭证。
group '[GROUP_ID]'
version '[VERSION]'
def artifactId = '[ARTIFACT_ID]'
apply plugin: 'maven'
uploadArchives {
  repositories {
    mavenDeployer {
      repository(url: 'xxxxx') {
        authentication(
          userName: '***',
          password: '***'
        )
    }
    snapshotRepository(url: 'xxxxx') {
      authentication(
        userName: '***',
        password: '***'
      )
    }
      pom.version = '$project.version'
      pom.artifactId = '$artifactId'
      pom.groupId = '$project.group'
    }
  }
}
步骤二:设置仓库下载配置
配置
allprojects {
  repositories {
    maven {
      url 'https://maven.aliyun.com/repository/public'
    }
    maven {
      credentials {
        username '***'
        password '***'
      }
      url 'xxxx'
    }
    maven {
      credentials {
        username '***'
        password '***'
      }
      url 'xxxx'
    }
  }
}

但是我不听他们的建议,这边我介绍一种比较方便的配置方法:

在模块的build.gradle里加入
ext {
    isRelease = false
    componentVersion = '0.0.1'
}

在下面的任意地方加入(因为gradle是按顺序编译的,引用必须要放在ext之下)
apply from: "publish.gradle"
这项目文件夹下创建一个publish.gradle 
apply plugin: 'maven-publish'
publishing {
    publications {
        debug(MavenPublication) {
            groupId maven_component_groupId  //gradle.properties里写入对应的值
            artifactId [project.name](http://project.name/)
            version "${isRelease ? componentVersion : "${componentVersion}-SNAPSHOT"}"
            artifact("$buildDir/aar/${[project.name](http://project.name/)}-debug.aar")
        }
    }
    repositories {
        maven {
            url "${isRelease ? maven_release_repo : maven_snapshots_repo}" //gradle.properties里写入对应的值
            credentials {
                username maven_user //gradle.properties里写入对应的值
                password maven_password //gradle.properties里写入对应的值
            }
        }
    }
}

这样,我们每次升级版本的时候,只用修改对应模块build.gradle里版本号就ok了
然后我们依次执行下面两行命令,将模块推送到远端:

./gradlew :MusicComponent:build
./gradlew :MusicComponent:publish

然后我们在引用模块的时候,只需要在上层模块build.gradle

implementation "${maven_component_groupId}:MusicComponent:0.0.1-SNAPSHOT"

这样我们就实现了远程依赖。接下来,我们只要一步一步更改版本号就可以完成组件升级。

你可能感兴趣的:(Android组件化实践)