使用 Hilt 进行依赖注入
使用 Hilt 简化依赖管理。使用 @HiltAndroidApp、@AndroidEntryPoint、@HiltViewModel、@Module、@Provides 和 @Singleton 作用域。
使用 Hilt 进行依赖注入 是 CoddyKit 上的免费 Android Academy 课时。 这是第 6 节课,共 6 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 6 节课。
什么是依赖注入?
依赖注入(DI)是指为对象提供它所需的内容,而不是让对象自行创建依赖项。
没有 DI 时,类会自行创建依赖项——耦合紧密且难以测试。有了 DI,依赖项会从外部注入——耦合松散,易于测试和替换。
手动 DI 与 Hilt
手动 DI 虽然可行,但项目规模扩大后会变得很麻烦:
// Manual DI — you create and pass everything:
val db = AppDatabase.getInstance(context)
val dao = db.userDao()
val repo = UserRepository(dao)
val factory = UserViewModel.Factory(repo)
val viewModel = ViewModelProvider(this, factory)[UserViewModel::class.java]
// With Hilt:
// Just annotate, Hilt does the wiring
@HiltViewModel
class UserViewModel @Inject constructor(private val repo: UserRepository) : ViewModel()添加 Hilt
将 Hilt 添加到项目中:
// project/build.gradle:
buildscript {
dependencies {
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.51'
}
}
// app/build.gradle:
plugins {
id 'com.google.dagger.hilt.android'
id 'kotlin-kapt'
}
dependencies {
implementation 'com.google.dagger:hilt-android:2.51'
kapt 'com.google.dagger:hilt-android-compiler:2.51'
}@HiltAndroidApp
使用 @HiltAndroidApp 为您的 Application 类添加注解。这是 Hilt 组件层次结构的入口点:
@HiltAndroidApp
class MyApp : Application()
// Also register in AndroidManifest.xml:
// <application android:name=".MyApp" ...>@AndroidEntryPoint
为需要注入依赖项的 Activity、Fragment 和 Service 添加 @AndroidEntryPoint:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var analytics: AnalyticsService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
analytics.logEvent("app_open")
}
}
@AndroidEntryPoint
class HomeFragment : Fragment() {
// Fragment's parent Activity must also be @AndroidEntryPoint
}@Inject — 构造函数注入
使用 @Inject 标记构造函数,告诉 Hilt 如何创建该类。Hilt 会自动解析所有参数:
class UserRepository @Inject constructor(
private val userDao: UserDao,
private val apiService: ApiService
) {
suspend fun getUsers() = userDao.getAll()
suspend fun syncFromNetwork() {
val users = apiService.fetchUsers()
userDao.insertAll(users)
}
}
// Hilt sees UserRepository needs UserDao and ApiService,
// and automatically creates and injects them.@HiltViewModel
使用 @HiltViewModel 为您的 ViewModel 添加注解,并使用 @Inject constructor。在 Fragment 中通过 by viewModels() 获取它:
@HiltViewModel
class UserViewModel @Inject constructor(
private val repo: UserRepository
) : ViewModel() {
val users = repo.getUsersFlow().asLiveData()
}
// In Fragment:
@AndroidEntryPoint
class UserFragment : Fragment() {
private val viewModel: UserViewModel by viewModels() // Hilt provides it
}@Module 与 @Provides
当 Hilt 无法使用构造函数注入时(例如接口、第三方类),可以通过 @Module 提供实例:
@Module
@InstallIn(SingletonComponent::class) // lives for app lifetime
object NetworkModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
}@Binds — 接口绑定
使用 @Binds 告诉 Hilt 某个接口应使用哪个实现:
interface AnalyticsService {
fun logEvent(name: String)
}
class FirebaseAnalytics @Inject constructor() : AnalyticsService {
override fun logEvent(name: String) { /* Firebase impl */ }
}
@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {
@Binds
@Singleton
abstract fun bindAnalytics(impl: FirebaseAnalytics): AnalyticsService
}Hilt 作用域
作用域控制注入实例可以存活多长时间:
@Singleton— 在应用的整个生命周期内使用同一个实例(ApplicationComponent)@ActivityRetainedScoped— 在配置更改后仍然存活@ActivityScoped— 每个 Activity 使用一个实例@FragmentScoped— 每个 Fragment 使用一个实例@ViewModelScoped— 每个 ViewModel 使用一个实例
使用 Hilt 进行测试
使用 Hilt 的测试支持,在测试中用伪实现替换真实依赖项:
@HiltAndroidTest
class UserRepositoryTest {
@get:Rule
val hiltRule = HiltAndroidRule(this)
@Inject
lateinit var repo: UserRepository
@Before
fun setUp() {
hiltRule.inject()
}
@Test
fun usersAreFetched() {
assertNotNull(repo)
}
}快速检查
哪个注解会告诉 Hilt 为整个应用生成 DI 组件层次结构?
回顾:Hilt 依赖注入
Hilt 让 Android 中的 DI 几乎可以自动完成:
- 在 Application 类上使用
@HiltAndroidApp - 在 Activity 和 Fragment 上使用
@AndroidEntryPoint - 对可注入的类使用
@Inject constructor - 对 ViewModel 使用
@HiltViewModel+@Inject constructor - 对第三方类和接口使用
@Module+@Provides - 使用
@Singleton在整个应用中共享一个实例
下一节:使用 Firebase Cloud Messaging 推送通知。
常见问题解答
「使用 Hilt 进行依赖注入」课时是免费的吗?
是的 — 「使用 Hilt 进行依赖注入」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 6 节课。
「使用 Hilt 进行依赖注入」这节课中我会学到什么?
使用 Hilt 简化依赖管理。使用 @HiltAndroidApp、@AndroidEntryPoint、@HiltViewModel、@Module、@Provides 和 @Singleton 作用域。 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Android Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 6 节课,共 6 节。
「使用 Hilt 进行依赖注入」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Android Academy 课中编写并运行代码吗?
能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- ViewModel 与 LiveData
- Room 数据库
- 协程与挂起函数
- 仓储模式
- Navigation 组件
- 使用 Hilt 进行依赖注入