Hilt 框架

温馨提示:本文最后更新于2025-12-19 15:31:18,某些文章具有时效性,若有错误或已失效,请在下方留言

HiltGoogle 官方推荐的 Android 依赖注入(DI)框架,基于 Dagger,极大简化了配置和使用成本,减少样板代码,与 ViewModel / Activity / Fragment / Service 深度集成,可以自动管理依赖生命周期。

概念 作用
@HiltAndroidApp Hilt 入口,生成容器
@AndroidEntryPoint 注入依赖的 Android 组件
@Inject 告诉 Hilt 如何提供依赖
@Module + @Provides 手动提供依赖

Hilt 常见注解

Hilt 注解
Hilt 注解

Application 级别注解

@HiltAndroidApp

  • 作用(Purpose)
    在 Android 应用的 Application 类 中初始化 Hilt
  • 使用方式(Usage)
    必须添加到 Application 类上。

Android 组件相关注解

这些注解用于让 HiltAndroid 组件中注入依赖。

@AndroidEntryPoint

  • 作用(Purpose)
    启用对 Android 框架类的依赖注入(例如:ActivityFragmentService)。
  • 使用方式(Usage)
    必须添加到需要注入依赖的 ActivityFragmentService 上。

@EntryPoint

  • 作用(Purpose)
    用于向非 Hilt 管理的类中注入依赖。
  • 使用方式(Usage)
    常用于 BroadcastReceiverContentProvider 等场景。

Module 相关注解

Module 用于定义 依赖是如何被提供的。

@Module

  • 作用(Purpose):
    标记一个类为 Hilt 模块,用于提供依赖。

@InstallIn

  • 作用(Purpose):
    指定模块的生命周期作用域(例如:SingletonComponentActivityComponent)。

常见组件(Common Components):

  • SingletonComponent:应用级别的单例依赖。
  • ActivityComponent:作用于单个 Activity 的依赖。
  • FragmentComponent:作用于 Fragment 生命周期的依赖。

@Provides

  • 作用(Purpose):
    定义一个方法,用于创建并提供某个依赖对象。

@Binds

  • 作用(Purpose):
    用于将接口与其具体实现类进行绑定。

  • 要求(Requirement):
    方法必须是 abstract(抽象方法)

注入相关注解

@Inject

  • 作用(Purpose):
    标记构造函数、字段或方法,用于依赖注入。

  • 使用方式(Usage):
    常用于构造函数注入、字段注入或方法注入

@Named

  • 作用(Purpose):
    用于区分相同类型的不同依赖实例

  • 使用方式(Usage):
    当同一类型存在多个实现或提供方式时使用。

@Qualifier

  • 作用(Purpose):
    @Named 的自定义版本,用于创建更语义化、更清晰的依赖标识

作用域注解

这些注解用于定义依赖对象的生命周期范围

@Singleton

  • 作用(Purpose):
    确保在整个应用生命周期内只创建一个依赖实例

@ActivityScoped

  • 作用(Purpose):
    依赖对象的生命周期与 Activity 保持一致,只要 Activity 存在,该依赖就存在。

测试相关注解

@HiltAndroidTest

  • 作用(Purpose):
    用于测试类中,启用 Hilt 测试环境

@UninstallModules

  • 作用(Purpose):
    在测试时移除指定的生产环境 Module,以便替换为测试用的依赖实现。

基本使用

添加依赖

// build.gradle.kts (Project: xxx)
plugins {
    ...
    alias(libs.plugins.ksp) apply false
    alias(libs.plugins.hilt.android) apply false
}
// build.gradle.kts (Module :app)
    ...
plugins {
    alias(libs.plugins.ksp)
    alias(libs.plugins.hilt.android)
}

android {
    ...
}

dependencies {
    implementation(libs.hilt.android)
    ksp(libs.hilt.compiler)
}
[versions]
hiltAndroid = "2.57.1"
kotlin = "2.2.0"


[libraries]
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hiltAndroid" }

[plugins]
ksp = { id = "com.google.devtools.ksp", version = "2.2.0-2.0.2" }
hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroid"}

构造器注入

Engine是需要注入的类。

/**
 * Engine.kt
 * 依赖
 * @Inject 告诉 Hilt 如何创建 engine 实例
 */
class Engine @Inject constructor() {
    // 单表达式函数
    fun start() = "Engine Started"
}

Car 是被注入的类。

/**
 * Car.kt
 * 依赖于 Engine 类
 */
class Car @Inject constructor(private val engine: Engine) {
    // 依赖从外部传入
    fun drive() {
        println(engine.start())
    }
}

AppModule 用于定义依赖是如何被创建和提供的,告诉 Hilt 如何构造所需的依赖对象。

/**
 * AppModule.kt
 * 
 * Hilt Module:
 * 用于定义依赖是如何被创建和提供的,告诉 Hilt 如何构造所需的依赖对象。
 *
 * @Module:
 * 用于标记一个类为 Hilt 模块(Module),告诉 Hilt 该类负责提供依赖对象(Dependency Provisioning)。
 */
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    /**
     * @Provides:
     * 用于告诉 Hilt 如何创建和提供一个依赖对象,即定义具体的依赖构造逻辑。
     *
     * @Singleton:
     * 用于确保 Hilt 在整个应用中只提供该依赖的单一实例(全局唯一)。
     */
    @Provides
    @Singleton
    fun provideEngine(): Engine {
        return Engine()
    }

    @Provides
    @Singleton
    fun provideCar(engine: Engine): Car {
        return Car(engine)
    }
}

AppComponent 连接 提供依赖的模块(Modules) 与 需要这些依赖的类,负责管理依赖的注入和生命周期。

/**
 * AppComponent.kt
 * 
 * Hilt Component:
 * 类似于一个桥梁,连接 提供依赖的模块(Modules) 与 需要这些依赖的类,负责管理依赖的注入和生命周期。
 */
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    /**
     * Hilt Component 接口:
     * 定义了 从 Dagger 的依赖图(Dependency Graph)中获取依赖对象的 API,即组件提供依赖访问的契约。
     */
    fun getCar(): Car
}

具体的使用。

class CarTest {
    @Test
    fun drive() {
        // Hilt/Dagger在编译期间生成 DaggerAppComponent 类
        val appComponent: AppComponent = DaggerAppComponent.create()

        // 获取 Car 实例
        var car: Car = appComponent.getCar()

        // 使用 Car
        println(car.drive())
    }

}

字段注入

字段注入(Field Injection) 是一种 依赖注入(Dependency Injection,DI) 技术,它通过注解将依赖对象直接注入到类的字段(属性)中,而不是通过构造函数传递。

这种方式通常使用 @Inject 注解,在 HiltDagger 等框架中非常常见。

字段注入主要用于无法或不适合使用构造函数注入的场景,例如 Android 框架类(如 ActivityFragment),因为这些类通常由系统创建,而不是由开发者手动实例化。

/**
 * 依赖
 * @Inject 告诉 Hilt 如何创建 engine 实例
 */
class Engine @Inject constructor() {
    // 单表达式函数
    fun start() = "Engine Started"
}
/**
 * 依赖于 Engine 类
 */
class Car {
    // 字段注入:engine 被注入到这个字段
    @Inject
    lateinit var engine: Engine

    fun drive() {
        println(engine.start())
    }
}
/**
 * AppModule.kt
 *
 * Hilt Module:
 * 用于定义依赖是如何被创建和提供的,告诉 Hilt 如何构造所需的依赖对象。
 *
 * @Module:
 * 用于标记一个类为 Hilt 模块(Module),告诉 Hilt 该类负责提供依赖对象(Dependency Provisioning)。
 */
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    /**
     * @Provides:
     * 用于告诉 Hilt 如何创建和提供一个依赖对象,即定义具体的依赖构造逻辑。
     *
     * @Singleton:
     * 用于确保 Hilt 在整个应用中只提供该依赖的单一实例(全局唯一)。
     */
    @Provides
    @Singleton
    fun provideEngine(): Engine {
        return Engine()
    }
}
**
 * AppComponent.kt
 *
 * Hilt Component:
 * 类似于一个桥梁,连接 提供依赖的模块(Modules) 与 需要这些依赖的类,负责管理依赖的注入和生命周期。
 */
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    /**
     * 添加一个用于字段注入的函数。
     * 该函数用于告诉 Dagger 将依赖项注入到 Car 类的字段中。
     */
    fun inject(car: Car)
}
class CarTest {
    @Test
    fun drive() {
        // Hilt/Dagger在编译期间生成 DaggerAppComponent 类
        val appComponent: AppComponent = DaggerAppComponent.create()

        // 获取 Car 实例
        var car: Car = Car()

        // 依赖注入到 Car 的字段中
        appComponent.inject(car)

        // 使用 Car
        println(car.drive())
    }

}

构造器注入 VS 字段注入

构造器注入 字段注入
依赖通过构造器传递 依赖直接注入到字段
更适用于非 Android 组件 常用于 Android 组件,如 ActivityFragment
依赖通常是不可变的(val)。 依赖通常是可变的(varlateinit var)。
更容易进行单元测试。 如果处理不当,测试相对更困难一些。

方法注入

方法注入(Method Injection) 是一种 依赖注入(Dependency Injection,DI) 技术,它通过方法参数传递依赖,而不是通过构造函数或字段进行注入。

这种方式在以下场景中非常有用:

  • 依赖只在某个方法中临时使用
  • 每次方法调用时依赖都会发生变化
/**
 * 依赖
 * @Inject 告诉 Hilt 如何创建 engine 实例
 */
class Engine @Inject constructor() {
    // 单表达式函数
    fun start() = "Engine Started"
}
/**
 * 依赖于 Engine 类
 */
class Car {
    lateinit var engine: Engine

    /**
     * 方法注入(Method Injection):
     * Hilt 会将 Engine 实例注入到该方法中。
     *
     * @engine Engine 的实例对象
     */
    @Inject
    fun installEngine(engine: Engine) {
        this.engine = engine
    }
    fun drive() {
        println(engine.start())
    }
}
/**
 * AppModule.kt
 *
 * Hilt Module:
 * 用于定义依赖是如何被创建和提供的,告诉 Hilt 如何构造所需的依赖对象。
 *
 * @Module:
 * 用于标记一个类为 Hilt 模块(Module),告诉 Hilt 该类负责提供依赖对象(Dependency Provisioning)。
 */
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    /**
     * @Provides:
     * 用于告诉 Hilt 如何创建和提供一个依赖对象,即定义具体的依赖构造逻辑。
     *
     * @Singleton:
     * 用于确保 Hilt 在整个应用中只提供该依赖的单一实例(全局唯一)。
     */
    @Provides
    @Singleton
    fun provideEngine(): Engine {
        return Engine()
    }
}
/**
 * AppComponent.kt
 *
 * Hilt Component:
 * 类似于一个桥梁,连接 提供依赖的模块(Modules) 与 需要这些依赖的类,负责管理依赖的注入和生命周期。
 */
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    /**
     * 添加一个用于字段注入的函数。
     * 该函数用于告诉 Dagger 将依赖项注入到 Car 类的字段中。
     */
    fun inject(car: Car)
}
class CarTest {
    @Test
    fun drive() {
        // Hilt/Dagger在编译期间生成 DaggerAppComponent 类
        val appComponent: AppComponent = DaggerAppComponent.create()

        // 获取 Car 实例
        var car: Car = Car()

        // 依赖注入到 Car 的字段中
        appComponent.inject(car)

        // 使用 Car
        println(car.drive())
    }

}
© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容