Skip to content

Hilt 依赖注入

源:使用 Hilt 实现依赖项注入

Hilt 是 Android 的依赖注入库,它构建在 Dagger 之上,提供了一种标准的方法将 Dagger 依赖注入合并到 Android 应用程序中。Hilt 通过为项目中的每个 Android 类提供容器并自动管理其生命周期,简化了 Dagger 的使用。

添加依赖

建议使用 KSP (Kotlin Symbol Processing) 来处理注解,因为它比 Kapt 更快。

项目根目录 build.gradle

kotlin
plugins {
    // ...
    id("com.google.dagger.hilt.android") version "2.51.1" apply false
    id("com.google.devtools.ksp") version "1.9.23-1.0.19" apply false
}

app 模块 build.gradle

kotlin
plugins {
    id("com.android.application")
    id("com.google.dagger.hilt.android")
    id("com.google.devtools.ksp")
}

dependencies {
    implementation("com.google.dagger:hilt-android:2.51.1")
    ksp("com.google.dagger:hilt-compiler:2.51.1")
}

Hilt 应用类

所有使用 Hilt 的应用都必须包含一个带有 @HiltAndroidApp 注解的 Application 类。

kotlin
import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class ExampleApplication : Application() { ... }

这个注解会触发 Hilt 的代码生成,包括应用的基础类,该类充当应用级依赖项容器。

将依赖项注入 Android 类

Application 类中设置了 Hilt 后,就可以使用 @AndroidEntryPoint 注解其他 Android 类(如 Activity、Fragment)。

kotlin
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    // 字段注入
    @Inject lateinit var analytics: AnalyticsAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
    }
}

Hilt 支持以下 Android 类:

  • Application (使用 @HiltAndroidApp)
  • ViewModel (使用 @HiltViewModel)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

注意:如果您使用 @AndroidEntryPoint 为某个 Android 类添加注解,则还必须为依赖于该类的 Android 类添加注解。例如,如果您为某个 Fragment 添加注解,则还必须为使用该 Fragment 的任何 Activity 添加注解。

定义绑定 (Bindings)

为了让 Hilt 知道如何提供不同类型的实例,我们需要使用构造函数注入或模块。

构造函数注入 (@Inject)

这是最简单的方法。在类的构造函数上添加 @Inject

kotlin
class AnalyticsAdapter @Inject constructor(
    private val service: AnalyticsService
) { ... }

Hilt 模块 (@Module)

有时候无法使用构造函数注入(例如接口、或者第三方库的类)。这时需要使用 Hilt 模块。

模块是一个带有 @Module 注解的类,它还需要 @InstallIn 注解来指定模块安装到哪个组件中(决定了绑定的生命周期)。

使用 @Binds 注入接口

kotlin
interface AnalyticsService {
    fun analyticsMethods()
}

class AnalyticsServiceImpl @Inject constructor() : AnalyticsService {
    override fun analyticsMethods() { ... }
}

@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {

    @Binds
    abstract fun bindAnalyticsService(
        analyticsServiceImpl: AnalyticsServiceImpl
    ): AnalyticsService
}

使用 @Provides 注入第三方类

kotlin
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    fun provideLoginRetrofitService(): LoginRetrofitService {
        return Retrofit.Builder()
            .baseUrl("https://example.com")
            .build()
            .create(LoginRetrofitService::class.java)
    }
}

预定义绑定 (@ApplicationContext)

Hilt 默认提供了一些常用的绑定,最常用的是 Context。我们无需手动编写 Module 来提供它。

限定符上下文类型适用组件
@ApplicationContextApplication Context任何组件 (Singleton, Activity, etc.)
@ActivityContextActivity ContextActivityComponent, FragmentComponent, ViewComponent
kotlin
class AnalyticsAdapter @Inject constructor(
    @ApplicationContext private val context: Context
) { ... }

组件和作用域 (Components & Scopes)

Hilt 提供了一组预定义的组件和对应的作用域注解。

Hilt 组件注入对象作用域注解
SingletonComponentApplication@Singleton
ActivityRetainedComponentViewModel@ActivityRetainedScoped
ActivityComponentActivity@ActivityScoped
FragmentComponentFragment@FragmentScoped
ViewComponentView@ViewScoped
ServiceComponentService@ServiceScoped

如果将 @Singleton 用于某个绑定,Hilt 会确保在整个应用中只创建一个该类型的实例。

在 ViewModel 中使用 Hilt

使用 @HiltViewModel 注解 ViewModel,并在构造函数中使用 @Inject

kotlin
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class ExampleViewModel @Inject constructor(
    private val repository: ExampleRepository,
    private val savedStateHandle: SavedStateHandle // Hilt 自动支持注入 SavedStateHandle
) : ViewModel() {
    // ...
}

然后在 Activity 或 Fragment 中像往常一样获取 ViewModel:

kotlin
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
    private val viewModel: ExampleViewModel by viewModels()
    // ...
}

限定符 (Qualifiers)

如果某个类型有多种实现(例如两个不同的 String 或两个不同的 Retrofit 实例),可以使用限定符。

  1. 定义注解:

    kotlin
    @Qualifier
    @Retention(AnnotationRetention.BINARY)
    annotation class AuthInterceptorOkHttpClient
    
    @Qualifier
    @Retention(AnnotationRetention.BINARY)
    annotation class OtherInterceptorOkHttpClient
  2. 在 Module 中使用:

    kotlin
    @Module
    @InstallIn(SingletonComponent::class)
    object NetworkModule {
    
        @AuthInterceptorOkHttpClient
        @Provides
        fun provideAuthOkHttpClient(
            authInterceptor: AuthInterceptor
        ): OkHttpClient {
            return OkHttpClient.Builder()
                .addInterceptor(authInterceptor)
                .build()
        }
    }
  3. 注入时使用:

    kotlin
    @Inject
    constructor(
        @AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient
    )