Hilt 使用简介
Hilt 是 Google 提供的官方依赖注入(DI)框架,基于 Dagger 2 构建,专为 Android 开发设计。它简化了依赖注入的配置和使用,自动为 Android 组件(如 Activity、Fragment、ViewModel)提供所需的依赖,使得代码更加清晰、模块化和易于测试。
以下是使用 Hilt 的基本步骤和示例:
1. 在项目中集成 Hilt
首先,你需要在 Android 项目的 build.gradle 文件中添加 Hilt 的依赖。
1.1 在项目根目录 build.gradle 中添加 Hilt 插件
gradle
复制编辑
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.google.dagger:hilt-android-gradle-plugin:2.40.5")
}
}
1.2 在应用模块 build.gradle 中应用 Hilt 插件和添加依赖
gradle
复制编辑
plugins {
id 'com.android.application'
id 'dagger.hilt.android.plugin' // 使用 Hilt 插件
}
android {
compileSdkVersion 30
defaultConfig {
applicationId "com.example.hiltapp"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
}
dependencies {
implementation 'com.google.dagger:hilt-android:2.40.5' // Hilt 核心库
kapt 'com.google.dagger:hilt-compiler:2.40.5' // Hilt 编译器
}
hilt-android是 Hilt 的核心库,提供依赖注入功能。hilt-compiler是注解处理器,生成必要的 Dagger 代码。
1.3 启用 Kapt(Kotlin 注解处理器)
如果你使用 Kotlin,需要启用 Kapt 以支持 Hilt 生成代码:
gradle
复制编辑
apply plugin: 'kotlin-kapt'
2. Hilt 的基本使用
2.1 在 Application 类中启用 Hilt
使用 @HiltAndroidApp 注解标记 Application 类,Hilt 会自动在应用启动时初始化。
kotlin
复制编辑
@HiltAndroidApp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Hilt 初始化
}
}
@HiltAndroidApp是 Hilt 提供的一个注解,用于启动依赖注入功能。
2.2 提供依赖
Hilt 使用 @Module 和 @InstallIn 注解提供依赖。通过 @Provides 注解的方法告诉 Hilt 你需要的依赖是如何创建的。
例如,创建一个提供网络服务的模块:
kotlin
复制编辑
@Module
@InstallIn(SingletonComponent::class) // 单例范围
object NetworkModule {
@Provides
@Singleton // 提供单例服务
fun provideApiService(): ApiService {
return ApiService()
}
}
@Module:标记一个类为依赖模块。@InstallIn(SingletonComponent::class):表示依赖的作用域为单例级别,即整个应用生命周期内有效。@Provides:标记方法提供依赖对象。
2.3 注入依赖
通过 @Inject 注解,Hilt 会自动注入需要的依赖。
kotlin
复制编辑
@HiltAndroidApp
class MyApplication : Application() {
@Inject lateinit var apiService: ApiService
override fun onCreate() {
super.onCreate()
// 在这里可以使用 apiService
}
}
@Inject:用于标记需要被注入的字段,Hilt 会自动提供该依赖。
2.4 在 Activity 或 Fragment 中注入依赖
在 Activity 或 Fragment 中,你可以使用 @AndroidEntryPoint 注解来标记需要依赖注入的组件。然后,使用 by inject() 或 by viewModels() 来获取依赖。
kotlin
复制编辑
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var apiService: ApiService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 使用注入的 apiService
apiService.getData()
}
}
@AndroidEntryPoint:标记Activity或Fragment,表示 Hilt 会为它们进行依赖注入。@Inject:标记依赖字段,Hilt 会自动注入它。
2.5 使用 ViewModel 和 @HiltViewModel 注解
ViewModel 是 Android 中用于管理 UI 数据的组件。通过 Hilt,我们可以将依赖注入到 ViewModel 中。
kotlin
复制编辑
@HiltViewModel
class MyViewModel @Inject constructor(private val apiService: ApiService) : ViewModel() {
fun fetchData() {
apiService.getData()
}
}
@HiltViewModel:将ViewModel标记为 Hilt 管理的组件,支持依赖注入。@Inject:标记构造函数,以便 Hilt 自动注入依赖。
在 Activity 或 Fragment 中使用 by viewModels() 来获取 ViewModel:
kotlin
复制编辑
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val myViewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
myViewModel.fetchData()
}
}
by viewModels():用于获取ViewModel实例并自动注入。
3. 进阶使用
3.1 作用域管理(Scope Management)
Hilt 提供了不同的作用域,允许开发者为依赖指定生命周期范围。常见的作用域有:
SingletonComponent:应用级单例,整个应用生命周期内有效。ActivityComponent:Activity生命周期内有效。FragmentComponent:Fragment生命周期内有效。
kotlin
复制编辑
@Module
@InstallIn(ActivityComponent::class) // 依赖与 Activity 生命周期相关
object ActivityModule {
@Provides
fun provideActivityDependency(): ActivityDependency {
return ActivityDependency()
}
}
@InstallIn(ActivityComponent::class)表示该依赖与Activity生命周期绑定,Activity销毁时,依赖也会被销毁。
3.2 使用 @Qualifier 注解
当多个依赖类型相同但实例不同的时候,可以使用 @Qualifier 来区分它们。
kotlin
复制编辑
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class NetworkClient
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class DatabaseClient
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@NetworkClient
fun provideNetworkClient(): OkHttpClient {
return OkHttpClient.Builder().build()
}
@Provides
@DatabaseClient
fun provideDatabaseClient(): OkHttpClient {
return OkHttpClient.Builder().build()
}
}
- 使用
@NetworkClient和@DatabaseClient来区分不同的OkHttpClient实例。
3.3 @AssistedInject 和动态参数
有时候 ViewModel 等需要动态参数,不能通过构造函数注入。这时可以使用 @AssistedInject。
kotlin
复制编辑
@AssistedInject
class MyViewModel @AssistedInject constructor(
private val savedStateHandle: SavedStateHandle,
@Assisted private val parameter: String
) : ViewModel() {
// 动态参数 parameter
}
@AssistedInject用于支持在运行时传递参数的注入。
4. 总结
Hilt 是一个强大的依赖注入框架,简化了 Android 中依赖注入的过程。通过使用 Hilt,开发者可以:
- 自动管理依赖:通过
@Inject自动注入所需的依赖。 - 生命周期管理:Hilt 可以根据组件的生命周期自动管理依赖的创建与销毁。
- 简化代码:通过注解和生成的代码,避免手动管理和配置复杂的依赖关系。
- 更好的测试性:Hilt 提供了便捷的测试功能,可以轻松模拟和注入依赖,进行单元测试。
通过合理使用 Hilt,可以让 Android 应用的架构更清晰、更解耦,并提高代码的可维护性和可测试性。
Hilt 源码分析
Hilt 是 Android 官方推荐的依赖注入(DI)框架,基于 Dagger 2 构建,它简化了 Dagger 的使用并自动化了很多配置,使得开发者能够更轻松地进行依赖注入。Hilt 提供了一个用于 Android 开发的专用 DI 解决方案,能够有效管理组件间的依赖关系,并使得代码更加清晰和可维护。
Hilt 的核心是 Dagger,但它通过一系列的 注解处理器,简化了 Dagger 2 的复杂性,并与 Android 架构组件(如 Activity、Fragment、ViewModel)紧密集成。本文将详细分析 Hilt 的源码实现原理,帮助更好地理解它是如何工作的。
1. Hilt 的核心组件
Hilt 核心组件主要由以下几个部分组成:
-
Hilt 注解:
@HiltAndroidApp@AndroidEntryPoint@HiltViewModel@InstallIn@Provides和@Inject
-
模块和组件:
- 模块(Module) :用于提供依赖的生成方法。
- 组件(Component) :由 Hilt 和 Dagger 生成,用于注入依赖。
-
生命周期管理:
- Hilt 管理的生命周期组件,如
ActivityComponent、FragmentComponent、SingletonComponent等。
- Hilt 管理的生命周期组件,如
2. Hilt 注解和工作流程
Hilt 主要依赖于注解处理器在编译时生成代码。通过一些注解,Hilt 自动化了很多 Dagger 2 配置的部分,简化了注入的过程。
2.1 @HiltAndroidApp
@HiltAndroidApp 注解用于标记 Application 类,Hilt 会在该类的 onCreate() 中进行初始化。这是 Hilt 的启动点。
kotlin
复制编辑
@HiltAndroidApp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Hilt 初始化
}
}
当 @HiltAndroidApp 注解应用到 Application 类时,Hilt 会自动生成一个基础类,用来初始化 DI 环境。
2.2 @InstallIn 和生命周期组件
@InstallIn 注解用于指示依赖应该安装在哪个生命周期组件中。它指定了某个模块的作用域(如单例或在 Activity、Fragment 生命周期内)。
kotlin
复制编辑
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
fun provideNetworkClient(): OkHttpClient {
return OkHttpClient.Builder().build()
}
}
SingletonComponent:模块在应用生命周期内有效。ActivityComponent:模块在Activity生命周期内有效。FragmentComponent:模块在Fragment生命周期内有效。
Hilt 会根据这些作用域自动管理依赖的生命周期,确保依赖的创建和销毁与 Android 组件的生命周期一致。
2.3 @HiltViewModel 和 @Inject
@HiltViewModel 注解用于为 ViewModel 提供依赖注入。Hilt 会根据 ViewModel 的生命周期管理它的依赖,并通过 @Inject 注解自动将依赖注入到 ViewModel 的构造函数中。
kotlin
复制编辑
@HiltViewModel
class MyViewModel @Inject constructor(
private val repository: MyRepository
) : ViewModel() {
// 使用注入的 repository
}
Hilt 会自动生成代码来提供这些依赖,并确保 ViewModel 的生命周期正确。
2.4 依赖注入工作流程
-
模块注册:
- 使用
@Module和@InstallIn定义模块,并通过@Provides注解提供依赖。
- 使用
-
依赖注入:
- 在需要依赖的类中,使用
@Inject注解标记构造函数或字段,Hilt 会自动处理依赖注入。
- 在需要依赖的类中,使用
-
生命周期管理:
- Hilt 根据
@InstallIn注解的生命周期管理依赖的创建和销毁。它使用不同的生命周期组件来控制依赖的生命周期。
- Hilt 根据
3. Hilt 和 Dagger 的关系
Hilt 构建于 Dagger 之上,实际上,Hilt 只是对 Dagger 进行了一层抽象,简化了它的使用流程。Dagger 是一个编译时的依赖注入框架,而 Hilt 使用了 Dagger 提供的功能,并为 Android 提供了一些特定的 API(如 @HiltViewModel、@AndroidEntryPoint 等)。
3.1 组件和模块生成
Hilt 使用 Dagger 生成组件和模块。每个通过 @InstallIn 标记的模块都会为不同的生命周期生成一个 Dagger 组件。这些组件在应用的生命周期内管理依赖的注入。
例如,SingletonComponent 是为应用生命周期生成的组件,确保所有在该作用域下的依赖是单例的:
kotlin
复制编辑
@InstallIn(SingletonComponent::class)
@Module
object AppModule {
@Provides
@Singleton
fun provideNetworkClient(): OkHttpClient {
return OkHttpClient.Builder().build()
}
}
3.2 Dagger 代码生成
Hilt 在编译时生成 Dagger 代码,通过注解处理器(@HiltAndroidApp、@AndroidEntryPoint 等)为我们自动创建 Dagger 的组件和依赖注入代码。开发者无需手动配置 Dagger 组件,Hilt 会根据生命周期自动管理它们。
Hilt 会生成一个基类 Hilt_MyActivity,负责管理 Activity 中的依赖注入:
kotlin
复制编辑
class MyActivity : AppCompatActivity() {
@Inject lateinit var networkClient: OkHttpClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Hilt 会自动注入依赖
}
}
Hilt 会生成类似以下的代码:
kotlin
复制编辑
class MyActivity_HiltInjector {
static void inject(MyActivity activity) {
// 注入 networkClient
activity.networkClient = networkClientProvider.get()
}
}
4. Hilt 的工作原理
-
注解处理:
- Hilt 使用注解处理器(
HiltProcessor)在编译时生成所有必要的代码。@HiltAndroidApp、@InstallIn、@Provides等注解将触发生成组件、模块、依赖注入代码。
- Hilt 使用注解处理器(
-
生成组件:
- Hilt 会为每个
@InstallIn注解的模块生成一个 Dagger 组件。这些组件负责管理依赖的创建、生命周期以及注入。
- Hilt 会为每个
-
自动注入:
- 当
@Inject注解应用到字段或构造函数时,Hilt 会为我们自动注入依赖。它通过生成 Dagger 组件来注入所需的依赖,并确保每个依赖的生命周期与Activity、Fragment或ViewModel等组件一致。
- 当
-
生命周期管理:
- Hilt 会根据作用域(如
SingletonComponent、ActivityComponent等)来管理依赖的生命周期。它会确保在依赖的生命周期结束时,自动销毁和清理这些依赖。
- Hilt 会根据作用域(如
5. Hilt 源码关键部分
5.1 @HiltAndroidApp 注解处理器
当我们在 Application 类中使用 @HiltAndroidApp 注解时,Hilt 会生成一个基础类,负责初始化 Hilt 环境。
kotlin
复制编辑
@HiltAndroidApp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Hilt 初始化
}
}
Hilt 会在编译时生成如下代码:
kotlin
复制编辑
class MyApplication_HiltComponents {
static void inject(MyApplication application) {
// 初始化 Hilt 环境
}
}
5.2 @Inject 和 @Provides 注解
@Inject 注解用于标记需要注入的构造函数或字段,而 @Provides 注解用于标记依赖提供方法。Hilt 通过生成代码来处理这些注解,确保在需要的时候提供正确的依赖。
5.3 @AndroidEntryPoint
@AndroidEntryPoint 注解用于标记 Activity、Fragment、Service 等 Android 组件,Hilt 会为这些组件生成必要的注入代码,自动将依赖注入到相应的组件中。
6. 总结
Hilt 是 Android 上的依赖注入框架,它简化了 Dagger 2 的使用,提供了专门为 Android 设计的注解和组件。Hilt 的工作原理通过注解处理器生成代码,自动管理生命周期和依赖注入。它不仅简化了依赖注入的配置,还与 Android 的生命周期(如 Activity、Fragment、ViewModel)紧密集成。
Hilt 的核心优势:
- 自动化依赖注入:减少了手动配置和代码编写。
- 生命周期管理:根据生命周期范围管理依赖,避免内存泄漏。
- 与 Android 组件紧密集成:简化了与 Android 的集成,尤其是
ViewModel和Activity、Fragment等。
通过深入理解 Hilt 和 Dagger 2 的原理,我们可以更好地使用它们来提升 Android 项目的可维护性、可测试性和扩展性。