【业务场景架构实战】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
    }
}

参考资料

相关推荐
歪歪1007 小时前
Qt Creator 打包应用程序时经常会遇到各种问题
开发语言·c++·qt·架构·编辑器
EndingCoder8 小时前
Electron 性能优化:内存管理和渲染效率
javascript·性能优化·electron·前端框架
野生技术架构师9 小时前
开发微服务的9个最佳实践
微服务·云原生·架构
一只叫煤球的猫10 小时前
2025年基于Java21的的秒杀系统要怎么设计?来点干货
后端·面试·性能优化
Xの哲學10 小时前
Linux RCU (Read-Copy-Update) 机制深度分析
linux·网络·算法·架构·边缘计算
Tadas-Gao11 小时前
阿里云通义MoE全局均衡技术:突破专家负载失衡的革新之道
人工智能·架构·大模型·llm·云计算
听风同学12 小时前
RAG的灵魂-向量数据库技术深度解析
后端·架构
武子康12 小时前
Java-118 深入浅出 MySQL ShardingSphere 分片剖析:SQL 支持范围、限制与优化实践
java·大数据·数据库·分布式·sql·mysql·性能优化
luoganttcc13 小时前
黑芝麻芯片 架构分析
架构·硬件架构