【业务场景架构实战】1. 多模块 Hilt 使用原则和环境搭建

凡傲之凌物,不必定以言语加人,有以神气凌之者矣,有以面色凌之者矣。

从这篇文章开始,我将记录在实战中进行的架构优化/升级方面的经验。目前我所承接的是一个 维护了7年,包含10余个复杂模块 的庞大 APP,有无数祖传代码累积。而我现在要做的,就是要为这一辆行驶中的小汽车更换掉老旧的轮胎,使它能够更长远、更稳定地运行下去。

这一系列的首篇文章,先从接入 Hilt 框架开始。

项目现状分析

这是一个运行在 Android 平台,配合智能穿戴终端使用的项目。该项目用于在手机上与智能穿戴设备进行配对、连接、设置等。其场景覆盖全面,复杂度高,是一个极好的研究对象:

  • 多种数据格式和传输协议:蓝牙协议、HTTPS、对称、非对称加密等。
  • 软硬件结合:结合智能穿戴设备传感器所采集到的各种数据,配对连接多种硬件,正向、反向兼容性需求高。
  • 深入系统:该项目涉及形形色色的系统 API 调用,同时,该项目所采集到的数据也会对外开放使用。
  • 大数据量处理 :由于智能穿戴设备采集到的数据是 7*24 小时的,存在海量数据在设备之间同步的场景。面临着多端上传数据不一致的问题。

这个项目规模庞大、场景复杂、迭代历史悠久、架构劣化严重,因此,我希望可以通过有意识地在架构方面进行升级优化,降低项目的维护成本,提升代码运行效率,更快地定位问题、开发新需求。

目标

首先明确架构升级要达到的目标:

  • 分层明确:各层级之间单向依赖,有明确的作用域和语义区分。
  • 高内聚低耦合:同一份逻辑不允许出现2次,以复用为设计目标。
  • 利于单元测试和集成测试:可以在开发时对某一数据源进行灵活替换,以便进行数据 mock、单元测试等。
  • 避免过度设计:平衡开发成本和收益。

具体实现

先从分层次入手,首先尝试引入 Hilt 作为依赖注入(DI)框架,代替手动初始化组件的原始方式。

Hilt 的优点与使用场景

  • 依赖解耦:不需要手动创建依赖对象,避免类之间强耦合。
  • 生命周期感知 :Hilt 可以把对象绑定到 Android 组件的生命周期(SingletonComponentActivityRetainedComponentViewModelComponent 等),Repository 是全局单例,UseCase 绑定到 ActivityViewModel 绑定到 ViewModel 生命周期。这样避免了资源泄漏或对象复用不当的问题。
  • 可测试性:可以灵活地替换为 Fake 或者 Mock 实现。
  • 可读性高:Hilt 的依赖图清晰,接手项目的工程师很容易理解"这个对象从哪来"。

个人理解是,对于有明确方向性的业务依赖场景(如 RepositoryUseCase、网络客户端、数据库 DAO 等),建议使用 Hilt。对于简单的静态工具场景,可以用 object 单例快速实现。

搭建 Hilt 依赖

首先来看本项目的架构缩略图:

这是一个多模块(module)的项目,其主模块是 main-app,它是一个空壳模块,仅用于完成 Application 的初始化。其具体业务逻辑拆分为不同的 business-module,通过 settings.gradle 集成在一起。

因此,在阅读完 Hilt 使用文档后,我了解到需要进行以下两方面的接入:

module 引入 plugin 引入 dependency 声明 kapt
main-app
business-wear 🚫

必须在应用层(app 模块)的 build.gradle 引入 Hilt 插件,因为:

  • @HiltAndroidApp 只能写在 Application 类 上,而 Application 只能存在于 app 模块。
  • Hilt 的 Gradle 插件会为 Application 生成 Hilt_*Application,所以 必须在 app 模块应用插件。

而为了使用 Hilt/Dagger 注解处理器,则必须在两个模块里声明 kapt

main-app/build.gradle

gradle 复制代码
plugins {
    id 'com.google.dagger.hilt.android'
}

dependencies {
    implementation project(":business-wear")
    implementation "com.google.dagger:hilt-android:2.x.x"
    kapt "com.google.dagger:hilt-android-compiler:2.x.x"
}

business-wear/build.gradle

gradle 复制代码
dependencies {
    implementation "com.google.dagger:hilt-android:2.x.x"
    kapt "com.google.dagger:hilt-android-compiler:2.x.x"
}

另外需要注意,Hilt 和 ARouter 兼容性不佳,需要在 app 的配置里增加以下代码:

gradle 复制代码
hilt {
    enableAggregatingTask = false
}

实现 Repository-ViewModel-Activity 代码

gradle 文件里完成上述配置后,代码里按照以下方式接入 Hilt:

1. 在 Application 中初始化

如果 Application 存在继承关系,要把注解加在 AndroidManifest.xml 中用到的那个 Application 类上面。

kotlin 复制代码
@HiltAndroidApp
class MyApp : Application()

2. 创建 Repository

Repository 类本身无需注解,对其构造函数进行 @Inject

用单例 onject RepositoryModule 创建一个工厂,并将其安装为进程内单例唯一 SingletonComponent::class

kotlin 复制代码
// Repository 用普通类
class UserRepository @Inject constructor() {
    fun getUserName(): String {
        return "Alice"
    }
}

// Hilt Module(声明作用域)
@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {
    @Provides
    fun provideUserRepository(): UserRepository {
        return UserRepository()
    }
}

3. ViewModel 注入 Repository

使用 @HiltViewModel 注解 ViewModel,并在构造函数里进行 @Inject

kotlin 复制代码
@HiltViewModel
class UserViewModel @Inject constructor(
    private val userRepository: UserRepository
) : ViewModel() {

    fun loadUser(): String {
        return userRepository.getUserName()
    }
}

4. 在 Activity 中使用 ViewModel

最后,在终端页面 Activity 上,用 @AndroidEntryPoint 进行注入。

kotlin 复制代码
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: UserViewModel by viewModels() // ===> 由 Hilt 管理

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        println(viewModel.loadUser()) // 输出 Alice
    }
}

参考资料

相关推荐
The Open Group1 天前
TOGAF® 架构库的隐藏力量:现代知识资产战略
微服务·云原生·架构
脚踏实地的大梦想家1 天前
【LangChain】P2 LangChain宏观架构深度解析:构建企业级大模型应用的首选框架
架构·langchain
Liquad Li1 天前
Salesforce 生态中的缓存、消息队列和流处理
缓存·架构·salesforce
wayne2141 天前
React Native启动性能优化实战:Hermes + RAM Bundles + 懒加载
react native·react.js·性能优化
文人sec1 天前
性能测试-jmeter15-性能项目计划流
分布式·jmeter·性能优化·grafana·prometheus·模块测试
UWA1 天前
游戏在高负载场景下,整机功耗控制在多少
游戏·unity·性能优化·游戏开发
武子康1 天前
Java-136 深入浅出 MySQL Spring Boot @Transactional 使用指南:事务传播、隔离级别与异常回滚策略
java·数据库·spring boot·mysql·性能优化·系统架构·事务
观望过往1 天前
Spring Cloud构建分布式微服务架构的完整指南
分布式·spring cloud·架构
StevenGerrad1 天前
【读书笔记】架构整洁之道 P5-2 软件架构
设计模式·架构·软件工程·依赖倒置原则·开闭原则
东临碣石821 天前
TOGAF考试95分通过,我的架构思维蜕变之旅
架构