首页 > 其他分享 >企业级项目组件化重构之路

企业级项目组件化重构之路

时间:2022-09-04 12:14:11浏览次数:93  
标签:重构 ft 企业级 MAVEN 模块 组件 login

前言

在之前的文章中,我们讲解了云音乐应用的基本库构建。今天,我们将进行一场 组件化代码重构

基于组件的库包系列文章 如下:

Android组件开发(一)——Maven私服构建

Android组件开发(二)——网络请求组件封装

Android组件开发(三)——图片加载组件封装

Android组件开发(四)——Process Keep-Alive组件的封装

Android组件开发(五)——音乐播放组件完整版打包

Android组件开发(六)——短视频播放组件封装

Android组件开发(七)——教你分析项目需求,从零开始实现

项目地址 github.com/ByteYuhb/an…

项目演示

090223022232_0device-2022-09-02-225448.png

1. 组件化重构效果

下面是我们重建前后的框架图对比:

重构前:

传统代码架构.png

重构后

组件化代码架构.png

  • ft_xxx 代表业务层模块 lib_xxx 表示一个基础库模块

重构后的架构图如下

服务接口调用.png

重构前的代码业务被封装在宿主应用程序中,业务耦合严重。如果修改了一个业务模块,就需要对整个app进行完整的测试,测试工作量巨大。
重构之后,我们只需要独立调试一个应用。

重构框架结构: 所有业务组件都通过 **ft_base_service** 交流

2. 组件化重构指南

    1. 单个业务可以单独调试,也可以作为lib提供给宿主应用
    1. 不允许直接调用同级的模块。比如我们的ft_home组件是不允许直接调用ft_login组件的,否则就不存在组件化的意义了。
    1. 组件之间的通信不能通过显示的类文件直接跳转。可以考虑使用 ARouter 框架进行解耦。
    1. 每个组件都可以打包成aar或者jar,上传到maven私服。宿主机使用时,可以直接引用私服中的aar包。

如果你能做到以上几点,你的应用就可以称为组件化框架应用。

3.组件化重构思路

重构思路.png

    1. 拆除 : 拆迁代码、拆迁资源、拆迁施工
      由于所有业务和资源都耦合在宿主应用程序中,因此需要将代码和资源分离到相应的模块中
      当然我们的build.gradle也需要拆分成不同的模块
    1. 抓住 : 提供外部接口
      组件之间没有直接的通信,需要通过暴露的接口进行外部通信。
    1. 测量 : 重复测试
      重构后代码需要反复测试,防止出现意外bug

4. 组件化重构过程

我在这里登录业务 ft_login 例如:

1. 步骤1 : 首先新建一个业务模块 ft_login ,然后在宿主应用程序中提取与登录功能相关的代码和资源 ft_login 中间

2. 第2步 :将与登录构建相关的依赖项分配给 ft_login 正在建设中。

3. 第 3 步 : 单独调试功能的实现

  • 3.1:在 gradle.properties 在以下位置创建一个全局变量: isRunAlone=真

  • 3.2:在 构建.gradle 中间:

    if(isRunAlone.toBoolean()){
    应用插件:'com.android.application'
    } 别的{
    应用插件:'com.android.library'
    }

    安卓 {
    compileSdkVersion 33
    构建工具版本“33.0.0”

    默认配置 {
    if(isRunAlone.toBoolean()){
    applicationId 'com.anna.ft_login'
    }
    ...
    }
    源集{
    主要的 {
    爪哇{
    srcDirs = ['src/main/java']
    }
    资源 {
    srcDirs = ['src/main/res']
    }
    添加{
    srcDirs = ['src/main/aidl']
    }
    显现 {
    if(isRunAlone.toBoolean()){
    srcFile 'src/main/manifest/AndroidManifest.xml'
    } 别的 {
    srcFile 'src/main/AndroidManifest.xml'
    }
    }
    }
    }
    }
    def 依赖列表 = [rootProject.depsLibs.okhttp,
    rootProject.depsLibs.gson,
    rootProject.depsLibs.appcompact,
    rootProject.depsLibs.design,
    rootProject.depsLibs.eventbus,
    rootProject.depsLibs.arouterapi,
    ':lib_network', ':lib_common_ui', ':ft_base_service']

    依赖{
    if(!isRunAlone.toBoolean()){
    依赖列表.each { 字符串依赖 ->
    依赖.startsWithAny(':lib', ':ft')? compileOnly(project(depend)):compileOnly(depend){
    开关(依赖){
    案例 rootProject.depsLibs.arouterapi:
    排除组:'com.android.support'
    休息;
    }
    }
    }
    } 别的 {
    依赖列表.each { 字符串依赖 ->
    依赖.startsWithAny(':lib', ':ft')?实施(项目(依赖)):实施(依赖){
    开关(依赖){
    案例 rootProject.depsLibs.arouterapi:
    排除组:'com.android.support'
    休息;
    }
    }
    }
    }
    //路由注解处理器
    annotationProcessor rootProject.depsLibs.aroutercompiler

    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    }

    复制代码

个别调试状态注意四点

  • 1.参考应用插件
  • 2.引入applicationId
  • 3. 为sourceSets引入不同的构建路径
  • 4.导入的库需要单独调试状态下使用 执行 导入,不能使用 只编译

实现以上四点, 只需打开 isRunAlone 即可作为单独的应用程序运行 .

4. 第四步:组件之间的通信

在这里,我们介绍一个 ft_base_service 模块,该模块用于实现组件之间的通信,需要调用其他业务模块才能使用该模块进行通信,
业务模块和 ft_base_service 通讯使用 路由 ARouter
关于 路由器 使用可以参考这篇文章:

Android开源系列——组件化框架Arouter——(一)使用详解

  • 1. 创建 ft_base_service ,在这个模块中:创建一个 登录服务 接口继承 提供者

引入 ARouter 依赖

 安卓 {  
 javaCompileOptions {  
 注释处理器选项 {  
 参数 = [AROUTER_MODULE_NAME:project.getName(),AROUTER_GENERATE_DOC:“启用”]  
 }  
 }  
 }  
 //路由核心api  
 实现 rootProject.depsLibs.arouterapi  
 //路由注解处理器  
 annotationProcessor rootProject.depsLibs.aroutercompiler  
 复制代码

创建登录服务:

 公共接口 LoginService 扩展 IProvider {  
 boolean hasLogin();  
 无效登录(上下文上下文);  
 }  
 复制代码
  • 2. 在 ft_login 在业务模块中实现LoginService接口

注意,因为这里使用了 ARouter 注解,所以也需要引入 路由器 依靠

 @Route(path = "/login/login_service")  
 公共类 LoginServiceImpl 实现 LoginService {  
 上下文上下文;  
 @覆盖  
 公共布尔 hasLogin () {  
 返回 UserManager.getInstance().hasLogined();  
 }  
  
 @覆盖  
 公共无效登录(上下文上下文){  
 LoginActivity.start(context);  
 }  
  
 @覆盖  
 公共无效初始化(上下文上下文){  
 Log.d("TAG", "LoginServiceImpl is init");  
 }  
 }  
 复制代码
  • 3. 在 ft_base_service 模块对 登录服务 依赖注入接口

    公共类 LoginImpl {

    @Autowired(name = "/login/login_service")
    公共登录服务 mLoginService;
    私有静态 LoginImpl mLoginImpl = null;
    公共静态 LoginImpl getInstance () {
    if (mLoginImpl == null) {
    同步(LoginImpl.class){
    if (mLoginImpl == null) {
    mLoginImpl = new LoginImpl();
    }
    返回 mLoginImpl;
    }
    }
    返回 mLoginImpl;
    }

    私人登录Impl(){
    ARouter.getInstance().inject(this);
    }
    公共布尔 hasLogin (){
    返回 mLoginService.hasLogin();
    }
    公共无效登录(上下文上下文){
    mLoginService.login(上下文);
    }

    }
    复制代码

作者使用了一个 单例类 LoginImpl , 在构造函数中 登录服务 依赖注入

ARouter.getInstance().inject(this);

那么宿主app或者其他模块在引用登录业务功能时,需要依赖 **ft_base_service** 模块,并使用 **LoginImpl** 接口可以使用。

这里解释一下,我们通常使用 四分量跳跃 也可以用这个方法来处理,只需要在服务接口中定义跳转接口即可。当然也可以使用Arouter的Activity跳转方式或者Fragment实例获取方式。

  • 5.代码打包aar上传到 maven私人服务器

更多关于这个maven私服的信息,请参考这篇文章:

Gradle 基础(六)——使用 Maven 发布组件化类库

这里我们封装了一个通用的组件发布库:

 应用插件:'maven'  
  
  
 上传档案{  
 存储库{  
 mavenDeployer {  
 // 是否快照版本  
 def isSnapShot = Boolean.valueOf(MAVEN_IS_SNAPSHOT)  
 def versionName = MAVEN_VERSION  
 if (isSnapShot) {  
 版本名称 += "-SNAPSHOT"  
 }  
 // 组件信息  
 pom.groupId = MAVEN_GROUP_ID  
 pom.artifactId = MAVEN_ARTIFACTID  
 pom.version = 版本名称  
  
 // 快照存储库路径  
 快照存储库(网址:uri(MAVEN_SNAPSHOT_URL)){  
 身份验证(用户名:MAVEN_USERNAME,密码:MAVEN_USERNAME)  
 }  
 // 发布仓库路径  
 存储库(网址:uri(MAVEN_RELEASE_URL)){  
 身份验证(用户名:MAVEN_USERNAME,密码:MAVEN_USERNAME)  
 }  
  
 println("#####################################"  
 + "\nuploadArchives = " + pom.groupId + ":" + pom.artifactId + ":" + pom.version + "." + pom.包装  
 + "\nrepository=" + (isSnapShot ? MAVEN_SNAPSHOT_URL : MAVEN_RELEASE_URL)  
 + "\n####################################"  
 )  
 }  
 }  
 }  
  
 复制代码

然后在对应的组件下面引用它:

 申请自:文件('../maven.gradle')  
 复制代码

直接在发布时 摇篮 在面板中单击 上传档案 任务

task面板.png

经过以上步骤,基本完成了登录组件的打包和发布,对外提供了登录组件接口。
其他组件也按照上述逻辑进行重构

更多详情可自行获取 项目源代码 查看。

5.组件化重构总结

组件化不仅是一种架构,更是一种理念。架构可以改变,但核心思想是统一的。拆分代码时要注意模块的粒度,并不是粒度越小越好。 ,模块分离良好,对后期的组件改造有很大帮助。
关于组件化的文章到此结束。组件化重构项目已上传至 Github。
以后会有
**插入** 项目改造。敬请关注。

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议。转载请附上原文出处链接和本声明。

这篇文章的链接: https://homecpp.art/3704/6415/0928

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/12250/57580411

标签:重构,ft,企业级,MAVEN,模块,组件,login
From: https://www.cnblogs.com/amboke/p/16654789.html

相关文章

  • 你应该使用受控组件来处理 React 中的密码吗?
    你应该使用受控组件来处理React中的密码吗?Photoby丹·纳尔逊on不飞溅我最近正在为一个客户开发一个项目,其中包括身份验证和登录页面。当我去设置用户名和密码的......
  • vue3 基础-组件间传值及校验
    本篇讲基于对页面组件化拆分后,组件之间如何进行数据传递,通常是父组件如何给子组件进行传值,子组件接收并进行数据校验后再使用.父子组件传值<!DOCTYPEhtml><html......
  • 修复:无法对未安装的组件执行反应状态更新。
    修复:无法对未安装的组件执行反应状态更新。在开发react.js应用程序时可能会遇到此错误:警告:无法对未安装的组件执行React状态更新。这是一个空操作,但它表明您的应用......
  • 4-《从零开始构建企业级推荐系统》读书笔记
    第1章推荐系统的时代背景为什么需要推荐系统流量利用长尾挖掘用户体验技术储备推荐什么东西只要是具有非普适性特点的东西,就可以用来做推荐,将其个性化推荐......
  • DevOps企业级
    DevOps计划部署编码<-----DevOps------>运维......
  • delphi 【增强型图片组件TcxImage】
    1.picture属性:加载图片2.隐藏边框:Style---BorderStyle:=ebsNone3.设置控件背景色:style---color4.properties属性设置:    5.禁用右键菜单.properties---Po......
  • delphi 【数字微调编辑框组件TcxSpinEdit】
      此控件仅支持数字数.默认情况下不支持小数点,但支持负数输入.1.设置控件支持小数点输入.properties---valueType:=vtFloat2.隐藏边框右边的微调按钮.pr......
  • vue3 基础-全局组件和局部组件
    组件和页面的关系可以理解为,组件是页面的一部分.形象地理解组件就和盖房子一样的,可以将房子粗略拆分3个组件(组成部分)房顶,房身,地基.同时房顶又可以拆分...........
  • vue 父子组件传值
    一、父传子  1.父组件使用v-bind绑定一个变量variable(v-bind:变量名="值")<Invitationvisible="dialogVisible"@getData="getdata"/>   2. 子组件用prop......
  • react-native 类组件调用函数组件里面的方法
    父组件class类组件,关键代码我用红色部部分标记importReactfrom"react";import{View,Text}from"react-native";importHomeModalChilderfrom"../../compon......