Hilt依赖注入简化Android代码

456 阅读2分钟

Hilt 是 Google 基于 Dagger 开发的 Android 专属依赖注入框架,它能显著简化 Android 应用的依赖注入代码。以下是如何使用 Kotlin 结合 Hilt 简化依赖管理的详细指南:


一、快速配置

  1. 添加 Gradle 依赖
// build.gradle (Module)
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("kotlin-kapt")
    id("com.google.dagger.hilt.android") // 添加 Hilt 插件
}

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

// build.gradle (Project)
buildscript {
    dependencies {
        classpath("com.google.dagger:hilt-android-gradle-plugin:2.48")
    }
}

二、基础用法

1. 初始化 Hilt

@HiltAndroidApp // 必须标记 Application 类
class MyApp : Application()

2. 自动注入 Activity/Fragment

@AndroidEntryPoint // 自动注入标记
class MainActivity : AppCompatActivity() {
    @Inject lateinit var myDependency: MyDependency // 字段注入

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        myDependency.doSomething() // 直接使用已注入的依赖
    }
}

三、依赖模块定义

1. 创建模块

@Module
@InstallIn(SingletonComponent::class) // 作用域为应用生命周期
object AppModule {
    @Provides
    @Singleton // 单例作用域
    fun provideNetworkClient(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .build()
    }
}

2. 组件作用域对照表

作用域注解对应组件生命周期
@SingletonSingletonComponentApplication
@ActivityScopedActivityComponentActivity
@FragmentScopedFragmentComponentFragment
@ViewScopedViewComponentView
@ViewModelScopedViewModelComponentViewModel

四、ViewModel 注入

@HiltViewModel
class MyViewModel @Inject constructor(
    private val repository: MyRepository
) : ViewModel() {
    // ViewModel 逻辑
}

// Activity/Fragment 中使用
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: MyViewModel by viewModels()
}

五、高级技巧

1. 限定符 (Qualifiers)

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AuthInterceptorOkHttpClient

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
    @AuthInterceptorOkHttpClient
    @Provides
    fun provideAuthOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .addInterceptor(AuthInterceptor())
            .build()
    }
}

2. 预定义限定符

class MyService @Inject constructor(
    @ApplicationContext context: Context, // 应用上下文
    @ActivityContext activityContext: Context // 当前 Activity 上下文
)

3. 接口绑定

@Module
@InstallIn(SingletonComponent::class)
interface ServiceModule {
    @Binds
    fun bindAnalyticsService(
        analyticsServiceImpl: AnalyticsServiceImpl
    ): AnalyticsService
}

六、常见问题解决

  1. 依赖无法注入

    • 检查是否添加了 @AndroidEntryPoint
    • 确认依赖提供方模块已正确安装到组件
    • 验证作用域是否匹配(如 Activity 作用域依赖不能在 Application 作用域模块提供)
  2. 循环依赖

    // 错误示例
    class A @Inject constructor(b: B)
    class B @Inject constructor(a: A)
    
    // 解决方案:使用 Lazy 延迟初始化
    class A @Inject constructor(private val b: Lazy<B>)
    

七、测试支持

@HiltAndroidTest
class ExampleTest {
    @get:Rule
    val hiltRule = HiltAndroidRule(this)

    @Inject
    lateinit var testDependency: TestDependency

    @Before
    fun init() {
        hiltRule.inject()
    }

    @Test
    fun testWithInjectedDependencies() {
        // 使用注入的测试依赖
    }
}

// 测试模块定义
@Module
@TestInstallIn(components = [SingletonComponent::class], replaces = [ProdModule::class])
object TestModule {
    @Provides
    fun provideTestDependency() = TestDependency()
}

八、优势总结

  1. 代码简化:相比传统 Dagger 减少 70% 的模板代码
  2. 作用域管理:自动处理 Android 组件的生命周期
  3. 可维护性:依赖关系显式声明,便于代码跟踪
  4. 测试友好:轻松替换测试依赖

对于新项目推荐直接使用 Hilt,现有 Dagger 项目可通过逐步迁移的方式整合。官方文档提供了详细的迁移指南和最佳实践。