【架构篇2】组件化方案及步骤

愿你成为自己的太阳,无需借谁的光
下文列出组件化的思路和步骤,按照如下思路和步骤,可以加快组件化工作的速度

1 诊断分析

1.1 诊断思路

【业务诊断】

列出包结构和主要类,按照业务维度进行诊断分析:

  1. 梳理业务组件:相关联的包或类归属到对应的组件下,根据用户的使用路径,查看这个类的依赖和引用情况;
  2. 梳理功能组件:查看前面业务组件多次引用的类,如果一个类被多个业务组件所引用,那么大概率这个类要被划分到功能组件的范围;
  3. 梳理技术组件:能不能放在任何一个应用里使用

【接口诊断】

根据类依赖和引用关系,找到业务边界类:

  1. 列出核心类的依赖和引用关系,Ctrl+鼠标左键找到引用类,逐个排查调用的地方,设计好业务间API接口

1.2 搜索诊断

包名 主要功能 核心类 类依赖及引用情况 重构优先级 组件划 重构操作 修改点 操作状态
adapter 主要存放列表的适配器 DefaultRecyclerAdapter 无依赖 1 基础组件 下沉 common 可复用 move-done

1.3 业务诊断

包名 主要功能 核心类 类依赖及引用情况 重构优先级 组件划分 重构操作 修改点 操作状态
activity 存放数据模型、工具类、ViewModel、Activity

2 组件化

3.1 准备工作

  1. 确保目标 Module 存在

若目标 Module 不存在,需先创建新 Module,创建步骤如下所示

如上图 File → New → New Module → Android Library,并确保在 settings.gradle 中已包含:

php 复制代码
include ':app', ':original_module', ':target_module'

include ':space'
  1. 在app中添加该Module,确保新增module会构建到工程中
scss 复制代码
//build.gradle :app
implementation(':space')
  1. 复制相关依赖

为了避免迁移时AS报错导致移动失败,可以提前将原Module中的依赖拷贝到创建的Module,然后同步项目,如:

java 复制代码
dependencies {
    implementation project(':login')
    implementation project(':common')
    implementation project(':config')
    implementation project(':common_ui')
}

确保可以迁移成功,后面再删除多余的依赖

  1. 更改targetSdk和JDK版本
kotlin 复制代码
apply plugin: 'com.android.library'
apply from: "${rootProject.projectDir}/constants.gradle"
apply from: "${rootProject.projectDir}/versions.gradle"
apply from: "${rootProject.projectDir}/template/module.gradle"
apply from: "${rootProject.projectDir}/create_module_api.gradle"
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
    compileSdk  build_versions.compile_sdk
    defaultConfig {
        minSdkVersion build_versions.min_sdk
        targetSdk  build_versions.target_sdk
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
        versionCode build_versions.version_code
        versionName build_versions.version_name
        archivesBaseName = prop_archivesBaseName
        //指定room.schemaLocation生成的文件路径
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString(),
                             AROUTER_MODULE_NAME  : project.getName(),
                             AROUTER_GENERATE_DOC : "enable"]
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_11.toString()
    }
    kapt {
        useBuildCache = true
        javacOptions {
            option("-Xmaxerrs", 500)
        }
        arguments {
            arg("AROUTER_MODULE_NAME": project.getName())
        }
    }
    flavorDimensions "versionCode", "area"
    //根据配置项,代码中会有一些差别
    productFlavors {
       //
    }
    dataBinding {
        enabled = true
    }
}
  1. 引入apply from : " ${ rootProject . projectDir } /create_module_api.gradle", 提供对外的接口

3.2 接口替换

  1. 如1.1和1.2中的表格,根据诊断结果,先定义好对外的接口,各个引用实例调用的地方都需要核查到
  2. 根据定义好的接口生成space-api.jar
  3. 找到原来引用的地方,进行接口替换

3.3 移动类文件

记得按照小步快跑,逐步验证的原则

  1. 首先拷贝所有资源
  • 考虑到多语言,res下的资源可以通过剪切的方式拷贝过去,这样的好处是既快又全,且能保留git提交记录,当类文件移动过来时,资源是全的。
  • 类移动完成编译验证ok后,用不上的再从两边Module中删除掉
  1. 移动类文件

方法一:

经过测试,简单快捷的方式是:在AS中将所有需要的类一次性剪切到新的module,既能最大程度避免import类重定向的问题,也能保留git提交记录,是目前测试到的最优方式。

方法二:

  • 使用 Refactor → Move(推荐,自动处理部分依赖)

按照诊断的结论,根据优先级来进行移动,优先级数字越小,表示越高优,则优先重构

  1. 右键点击要移动的类文件,选择 Refactor → Move...(或按 F6)。
  2. 在弹出窗口中:
    1. To directory :选择目标 Module 的包路径(如 target_module/src/main/java)。
    2. Search for references:勾选此项,自动修正原 Module 中的引用。
  3. 确认移动
    点击 Refactor,Android Studio 会尝试自动更新代码中的引用(但可能仍需手动检查)。
  • 迁移完记得在git-Local Changes中解决引用错误,由于类都是move过来的,将引用还原回去,就可以解决大部分问题

方式二只适用于小范围重构

3.4 解决编译错误

  1. 清理项目:
    Build → Clean ProjectBuild → Rebuild Project
  2. 手动修正错误
    1. 包名错误 :检查所有 import 语句是否指向新包名。
    2. 缺失依赖 :若目标 Module 需要第三方库,需在其 build.gradle 中添加依赖。

这步会比较耗时,可以在Git---Local Changes逐个浏览更改

3.5 验证功能

  1. 启动 App:手动测试相关功能是否正常。
  2. 检查日志 :关注运行时是否抛出 ClassNotFoundException 或资源加载错误。

验证功能的过程中会遇到各种忽略的奇怪错误,保持耐心,逐个解决即可,常见的错误见3.6节

3.6 常见问题与解决

  1. 问题1 Cannot resolve type 'controller'

【原因】 类的路径变动后,DataBinding定义的类路径并不会自动修正

  1. 问题2 Found UnSupported class type

【原因】由于类都是剪切过来的,引用的路径会有错误的情况,继承com.alibaba.android.arouter.facade.template.IProvider的接口中有类引用路径错误

  1. 问题3 Didn't find class "com. ..PictorialApplication"

【原因】build缓存文件未清掉,导致编译时异常,记得将clean project,并将未clean掉的build目录都删除掉

  1. 问题4 ARouter$$Group is defined multiple times

【原因】由于类的迁移未更改Route path或name的前缀,不同的module中,使用了相同的前缀,导致出现如上错误

  1. ProGuard混淆的规则记得同步更改

3.7 最佳实践

  1. 逐步操作:将整个流程进行解耦,每一步想清楚弄完后再进行下一步,逐步验证,这样即使有问题也是小问题,很容易排查,避免大规模改动后难以定位问题。
  2. 优先使用 Refactor 工具:减少手动操作导致的遗漏。
  3. 模块职责单一化:确保目标 Module 的职责清晰,移动的过程中难免有遗漏,记得做好注释,后续很快可以找到解决

3 解耦重构

3.1 接口优化

在组件化拆分完成后,根据第1章中诊断分析的现状,继续分析当前类的依赖和引用是否合理,进行组件内重构: 详见1.3中的表格

4 历史缺陷分析

4.1 缺陷分析

取2024.1-2024.12的缺陷进行分析如下:

4.2 代码优化

根据bug产生的原因,从代码角度最大程度规避问题:

缺陷类型 原因 解决方法
跳转index错误 处理的地方有多处,且处理的代码样式不一样,会漏掉 将关键的判断方法抽取为统一的方法,使任何人添加代码都不会出错

5 指导手册

从测试和开发角度进行分析,为了提高效率,输出指导手册

相关推荐
欧达克5 小时前
AI 嘴替,社交平台反杠机器人:第 0 篇-扬帆起航
程序员·github
安妮的心动录16 小时前
安妮的2025 Q1 Review
程序员
摆烂工程师19 小时前
保姆教程:2025年 ChatGPT Plus 的订阅升级攻略和支付失败的解决方式
前端·后端·程序员
京东零售技术1 天前
京东零售技术专家亮相多场峰会,诚邀伙伴们共探前沿!
程序员
Captaincc1 天前
程序员究竟怎样用 AI?深度解读 WIRED 调查报告《How Software Engineers Actually Use AI》
程序员·ai编程
这里有鱼汤1 天前
Python逆天改命,3分钟做出高颜值GUI程序
后端·python·程序员
摆烂工程师1 天前
炸裂了~兄弟们,GPT4o出图效果太好了
前端·后端·程序员
马可奥勒留1 天前
我的管理日记(1)
程序员
Goboy1 天前
我曾经被腾讯云一条龙服务过
后端·程序员·架构
Goboy2 天前
腾讯混元T1正式版发布
后端·程序员·架构