Anvil Kotlin 完全指南:安装、方法与实战示例
1. 什么是 Anvil?为什么需要它?
Anvil 是一个专为 Kotlin 设计的代码生成库,它基于 Dagger 和 Hilt 依赖注入(DI)框架运行。其核心目标是消除编写与 DI 模块、组件、工厂和入口点相关的样板代码的繁琐工作。您无需手动创建和注解 Dagger 模块,只需用 Anvil 注解标记类,该库便会在编译阶段自动生成所有必要代码。
为什么需要它?在大型 Android 或 Kotlin Multiplatform 项目中,需要在依赖图中注册的类可能多达数百个。每次添加新的 Dagger 模块、编写 @Provides 或 @Binds 代码,不仅速度慢、容易出错,还会增加重构的难度。Anvil 通过基于简单注解自动创建模块来解决这一问题。这在基于功能模块(feature modules)的架构中尤其有用,每个模块都可以独立构建和测试。
Anvil 与 Gradle 紧密集成,并使用 Kotlin Symbol Processing (KSP) 或 KAPT 来生成代码。它同时支持 Dagger 和 Hilt,并且可以在多平台项目中运行。该库由 Square 公司开发,该公司以 Android 开发工具(如 Retrofit、OkHttp、Moshi)而闻名。
2. 安装指南
要将 Anvil 集成到您的 Kotlin/Gradle 项目中,请在 build.gradle.kts 文件(项目根级别)中添加以下依赖:
// 在根目录的 build.gradle.kts 中
plugins {
id("com.google.dagger.hilt.android") version "2.48" apply false
id("com.squareup.anvil") version "2.4.7" apply false
}
然后,在应用模块(例如 app/build.gradle.kts)中:
plugins {
id("com.android.application")
kotlin("android")
id("com.google.dagger.hilt.android")
id("com.squareup.anvil")
}
android {
// ... 您的 Android 配置
}
dependencies {
// Hilt
implementation("com.google.dagger:hilt-android:2.48")
kapt("com.google.dagger:hilt-compiler:2.48")
// Anvil
implementation("com.squareup.anvil:annotations:2.4.7")
ksp("com.squareup.anvil:compiler:2.4.7") // 如果您不使用 KSP,也可以使用 kapt
}
如果您使用 KSP 而不是 KAPT,请确保已添加 KSP 插件:
plugins {
id("com.google.devtools.ksp") version "1.9.0-1.0.13"
}
同步 Gradle 后,Anvil 即可使用。
3. 快速上手 —— 最小工作示例
让我们看一个最简单的例子:我们有一个 UserRepository 类,需要将其注入到 MainViewModel 中。
步骤 1. 创建要注入的接口或类:
// UserRepository.kt
class UserRepository @Inject constructor() {
fun getUser(): String = "John Doe"
}
步骤 2. 创建需要使用依赖的类:
// MainViewModel.kt
class MainViewModel @Inject constructor(
private val userRepository: UserRepository
) {
fun getUserName(): String = userRepository.getUser()
}
步骤 3. 使用 Anvil 创建 Hilt(或 Dagger)组件:
// AppComponent.kt
@Singleton
@Component
@MergeComponent(AppScope::class) // Anvil 注解
interface AppComponent {
fun inject(app: MyApplication)
}
// AppScope.kt (定义作用域)
@Scope
@MustBeDocumented
annotation class AppScope
步骤 4. 使用 Anvil 注解在依赖图中注册类:
// UserRepository.kt (添加 Anvil 注解)
@ContributesBinding(AppScope::class)
class UserRepository @Inject constructor() {
fun getUser(): String = "John Doe"
}