Android开发[8]:组件分包

6 阅读11分钟

Android组件分包

今日目标

  • 掌握组件分包的2种核心思路(按功能分包、按业务分包)及实战方法。
  • 精通组件化工程全维度规范(命名、代码、配置、依赖),完成现有组件化工程的分包重构与规范优化。
  • 规避分包和规范相关的高频踩坑点,提升工程可维护性、可扩展性和团队协作效率。

组件分包

价值

  • 解决组件内部结构混乱、代码冗余、维护成本高、团队协作低效的痛点。
  • 实现组件内部高内聚、组件之间低耦合,让项目结构清晰、可维护、可扩展。
  • 同时降低新人上手成本,提升团队协作效率。

2种分包思路

  • 按功能分包
  • 按业务分包
按功能分包
  • 将组件内部代码按功能模块划分:ui、model(数据模型)、tool、service、api、res等。
  • 适用于小型组件或单一组件。
  • 功能划分清晰、上手简单。
按业务分包
  • 将组件内部代码按具体业务场景划分:例user组件分为login、register、detail、setting等。
  • 适合大型组件或业务复杂组件。
  • 业务隔离彻底、后续迭代维护便捷。
选型建议
  • 基础组件:优先按功能分包,功能相对固定,侧重复用。
  • 业务组件:优先按业务分包,业务迭代频繁,侧重隔离。
  • 小型项目:先按功能分包,熟练后过渡到业务分包。
  • 大型项目:统一采用按业务分包为主、功能分包为辅的混合模式,兼顾业务隔离和功能复用。

分包实战

本示例以壳工程+base+user为例,base组件按功能分包、user组件按业务分包。实际项目按自身架构调整分包。

每个组件内按“ui(页面)、model(数据模型)、repository(数据仓库)、tools(工具)、common(公共资源)”划分目录,结构统一。

准备工作
  • 1.梳理现有项目结构,避免重构混乱
  • base组件:工具类、接口、实体类、资源文件等。
  • user组件:Activity、接口实现、工具类、资源文件等。
  • 分包目的:不改变原有功能,仅优化结构。
  • 2.统一分包命名规范,提前约定,避免混乱
  • 功能分包命名
    • ui:基础UI相关(例:BaseActivity、BaseFragment、通用控件)
    • model:实体类、数据模型(例:UserInfo、BaseResponse)
    • tools:通用工具类(例:SPTool、MMKVTool、CoroutineTool)
    • service:存储公共接口(例:IUserService、IComponentLifecycle)
    • api:网络请求相关
    • core:存储核心配置(例:Application、AppContext等)
    • res:资源文件(按Android原生规范划分,drawable、layout、values等)
  • 业务分包命名:以user为例
    • login:登录相关(LoginActivity、登录工具类、登录数据处理类)
    • detail:用户详情相关(UserDetailActivity、详情相关数据处理类)
    • common:user组件公共内容(UserServiceImpl、UserComponentLifecycle等)
    • res:user组件专属资源文件
base组件按功能分包

base组件作为基础组件,功能相对固定,按功能分包,重点实现功能模块化、代码复用。

  • 1.创建base组件分包目录
// 在base组件的java/com/xxx/base目录下,创建以下分包目录(按功能划分):
// 1. ui:基础UI相关
// 2. model:实体类、数据模型
// 3. tools:通用工具类
// 4. service:公共接口
// 5. core:核心配置
// 目录结构如下:
base/
├── java/com/xxx/base/
│   ├── ui/          // 基础UI
│   ├── model/       // 实体类
│   ├── tools/       // 工具类
│   ├── service/     // 公共接口
│   └── core/        // 核心配置
└── res/             // 基础资源
  • 2.迁移代码至对应分包
  • 3.检查代码,确认包名引用修改为新包名,混淆保留代码使用新包名路径
  • 4.同步项目打包验证
user组件按业务分包

user组件作为业务组件,业务迭代频繁,按业务分包,实现业务隔离,方便后续迭代维护。

  • 1.创建user组件分包目录
// 在user组件的java/com/example/user目录下,创建以下分包目录(按业务划分):
// 1. login:登录相关
// 2. userDetail:用户详情相关
// 3. common:user组件公共内容
// 目录结构如下:
user/
├── java/com/xxx/user/
│   ├── login/       // 登录业务
│   ├── detail/      // 用户详情业务
│   └── common/      // 公共内容
└── res/             // 业务专属资源
  • 2.迁移代码至对应分包
  • 3.检查代码,确认包名引用修改为新包名,混淆保留代码使用新包名路径
  • 4.同步项目打包验证

项目规范

  • 命名规范
  • 代码规范
  • 配置规范
  • 依赖规范

命名规范

核心原则:见名知意、统一格式、避免歧义。遵循驼峰命名规范。

  • 1.包名规范
    • 基础格式:com.公司名.项目名com.公司名.组件名
    • 分包包名:基础格式.分包名
    • 禁止:包名使用拼音、无意义字母,禁止大小写混乱
  • 2.类名规范
    • Activity:Activity后缀,首字母大写(例:LoginActivity)
    • Fragment:Fragment后缀,首字母大写(例:UserDetailFragment)
    • 工具类:Tool后缀,首字母大写(例:SPTool、MMKVTool)
    • 实体类:无后缀,首字母大写(例:UserInfo、BaseResponse)
    • 接口:I开头,首字母大写(例:IUserService、IComponentLifecycle)
    • 单例类:可加Manager后缀(例:FlowBusManager、ComponentLifecycleManager)
    • 禁止:类名使用缩写(除非通用缩写,如MMKV、ARouter)、无意义名称
  • 3.方法名规范
    • 方法名首字母小写,驼峰命名,见名知意
    • 点击事件:on+控件名+Click(例:onLoginBtnClick)
    • 数据读写:get+数据名、put+数据名(例:getString、putParcelable)
    • 初始化:init+功能名(例:initMMKV、initARouter)
    • 禁止:方法名使用无意义字母、拼音,禁止方法名过长或过短
  • 4.变量名规范
    • 首字母小写,驼峰命名,见名知意
    • 控件变量:控件类型缩写+控件功能(例:tvUserName、btnLogin)
    • 常量:全大写,下划线分隔(例:VAL_MAX_COUNT = 10)
    • 禁止:变量名使用单个字母(例:a、b)、拼音,禁止变量名与类名重复
  • 5.资源文件规范
    • 布局文件:组件名_业务名_功能名(例:user_login_activity、base_common_layout)
    • 控件id:控件类型缩写_功能名(例:tv_user_name、btn_login)
    • 图片资源:组件名_功能名_状态(例:user_avatar_default、base_ic_back)
    • 字符串资源:组件名_功能名(例:user_login_title、base_toast_success)
    • 禁止:资源文件使用中文、无意义名称,禁止不同组件资源重名(可加组件前缀区分)

资源命名优化:将user组件的所有资源添加user_前缀

  • 布局文件:user_login_activity.xml、user_profile_fragment.xml
  • 图片资源:ic_user_avatar.png、ic_user_setting.png
  • 字符串资源:<string name="user_login_title">登录</string>
  • 避免与base组件、其他业务组件资源冲突。

代码规范

核心原则:简洁、规范、可复用、无冗余。借助CheckStyle插件辅助规范检查。

  • 1.代码格式规范
    • 缩进:4个空格(Android Studio默认),禁止使用Tab缩进
    • 空行:方法之间、类之间留1行空行,逻辑块之间留1行空行,避免连续空行
    • 括号:if、for、while等语句的括号紧跟关键字(if (condition) {),第一行语句另起一行
    • 注释:关键逻辑、复杂方法添加注释(// 单行注释,/** 多行注释 */),注释简洁明了,禁止无用注释
  • 2.代码复用规范
    • 重复代码:提取为工具类或公共方法(例:多次使用的字符串处理、弹窗逻辑)
    • Activity/Fragment:继承base组件的BaseActivity/BaseFragment,统一初始化操作
    • 工具类:统一放入base组件tools分包,避免各组件重复创建工具类
  • 3.代码冗余规范
    • 删除无用代码:注释掉的代码、未使用的方法、变量,及时删除
    • 简化代码:使用Kotlin特性(例:空安全、扩展函数、lambda表达式)简化代码,避免冗余
  • 4.异常处理规范
    • 关键逻辑(例:数据读写、网络请求)添加异常捕获(try-catch),避免崩溃
    • 禁止:直接catch Exception,需针对性捕获具体异常(例:NullPointerException、IOException)

配置规范

核心原则:集中管理、统一配置,贴合Version Catalog依赖管理规范,避免配置分散

  • 1.版本配置规范:所有依赖版本、插件版本,统一在Version Catalog(gradle/libs.versions.toml)中管理,禁止硬编码版本
  • 2.构建配置规范
    • 所有组件的compileSdk、minSdk、targetSdk,统一通过Version Catalog引用,确保版本一致
    • 壳工程统一配置签名、buildTypes(debug/release),各组件无需重复配置
// 示例:base组件build.gradle中,compileSdk引用Version Catalog版本
android {
    ...
    compileSdk {
        version = release(libs.versions.compileSdk.get().toInt()) {
            minorApiLevel = 1
        }
    }

    defaultConfig {
        minSdk = libs.versions.minSdk.get().toInt()
        targetSdk = libs.versions.targetSdk.get().toInt()
        ...
    }
}
...
  • 3.ARouter配置规范
    • 路由path格式:/组件名/页面名(例:/user/UserLoginActivity、/main/MainActivity)
    • 路由extras统一管理,避免随意设置,便于拦截器中实现页面拦截
    • 所有路由页面添加@Route注解,确保路径唯一,无冲突
  • 4.Hilt配置规范
    • 单例类添加@Singleton注解,Module类添加@Module、@InstallIn注解,确保注入正常
    • 组件间注入的接口,统一在base组件service分包中定义,避免接口分散
    • 禁止:重复提供Hilt实例,避免注入冲突
  • 5.混淆配置规范
    • 全局混淆(壳工程)配置公共规则,组件混淆配置专属规则
    • 混淆规则按包名保留,避免逐个类保留(如-keep class com.xxx.base.** {*;})
    • 新增分包后,检查混淆规则,确保所有核心类(工具类、接口、实体类)不被混淆

依赖规范

核心原则:依赖统一、隔离清晰、无冗余,避免依赖混乱。

  • 1.依赖引用规范:所有依赖均通过Version Catalog(libs.xxx)引用,禁止硬编码依赖
  • 2.依赖类型规范
    • base组件:公共依赖用api暴露(如ARouter、MMKV),内部依赖用implementation
    • 业务组件(user):仅依赖base组件,内部依赖用implementation,禁止使用api
    • 壳工程:仅依赖base和业务组件,不直接引入第三方依赖,避免重复引入
  • 3.依赖冗余规范
    • 定期清理无用依赖(Android Studio会提示unused),同步清理Version Catalog中的冗余配置
    • 避免重复引入同一依赖(例:base组件已暴露ARouter,user组件无需再引入)
  • 4.依赖兼容规范
    • 确保第三方依赖与Android Gradle插件、Kotlin版本兼容(通过Version Catalog统一管理版本)
    • 新增依赖时,先在Version Catalog中配置,再引用,确保版本统一

综合测试

对分包重构和规范优化后的工程进行全面测试,确保功能正常、规范达标、可正常上线。

  • 测试核心:覆盖分包后所有功能,验证分包和规范的合理性,确保无报错、无功能失效

测试范围

  • 1.debug模式测试
  • 运行壳工程,逐一测试以下功能:
    • ① ARouter路由:页面跳转(MainActivity→LoginActivity、MainActivity→UserActivity)、参数传递正常;
    • ② Hilt依赖注入:IUserService接口、GlobalDataManager单例注入正常,接口调用正常;
    • ③ 数据共享:DataStore、MMKV、全局单例的跨组件数据读写正常;
    • ④ 组件生命周期:App启动、退出时,组件加载、卸载正常,日志打印正常;
    • ⑤ 所有分包模块:代码可正常调用,无包名错误、引用错误;
  • 验证规范:检查项目命名、代码格式、配置、依赖,确保符合规范要求。
  • 2.release模式测试
  • 配置签名,运行release版本,重复debug模式的所有测试用例;
  • 验证要点:release模式下所有功能正常,无混淆失效、依赖冲突,包体积正常;
  • 重点验证:分包后ARouter路由、Hilt注入、MMKV数据存储功能正常,无报错。

踩坑点

坑点1:分包后包名引用错误,导致编译报错

  • 原因:代码迁移后未修改包名引用,或包名拼写错误。
  • 修复:检查并修正所有代码的包名引用、包名拼写,同步修改ARouter、Hilt相关注解的包名,确保一致。

坑点2:分包后ARouter路由跳转失败

  • 原因:路由path冲突、页面包名修改后未同步更新路由注解,或ARouter未注入。
  • 修复:检查路由path唯一性,同步更新路由注解的包名,确保Activity继承BaseActivity(统一ARouter注入)。

坑点3:分包后Hilt注入为null

  • 原因:单例类/接口的包名修改后,未同步修改Hilt Module中的引用,或Activity未添加@AndroidEntryPoint注解。
  • 修复:更新Hilt Module中的包名引用,确保所有需要注入的Activity添加@AndroidEntryPoint。

坑点4:分包过细或混乱,导致维护效率降低

  • 原因:未明确分包思路,盲目拆分。
  • 修复:遵循“按功能/业务分包”原则,base模块按功能、业务组件按业务,避免过度拆分,确保分包结构清晰、合理。

坑点5:规范不统一,命名、代码格式混乱

  • 原因:未提前约定规范,或执行不彻底。
  • 修复:制定统一的工程规范手册,逐一检查优化,养成规范编码习惯,增加review环节检查代码。

坑点6:分包后依赖冗余,导致依赖冲突

  • 原因:业务组件重复引入base组件已暴露的依赖。
  • 修复:清理业务组件中的重复依赖,确保仅依赖base组件,所有第三方依赖通过base组件api暴露,或通过Version Catalog统一管理。