Hilt 是干什么的?
它是 Google 为Android开发提供的场景化依赖库,皆在减少项目中进行的手动依赖注入。
Hilt 为项目中的每个 Android 类提供容器并自动管理它们的生命周期,为应用程序提供了 DI的标准方法。它是从 Dagger 库的基础上进行构建的,因为 Dagger提供的编译时正确性、运行时性能、可伸缩性并且从AndroidStudio支持Dagger中获益。
相比Dagger,Hilt有那些优化?
Hilt的实现要比Dagger简单的多,使用Dagger实现依赖注入,需要去编写modules、components等等。每次去创建一个新的Android组件,比如 Activity、Fragment时,我们都需要将它们手动添加到modules中。
使用 Hilt 前的准备工作
- 添加依赖 在项目的根目录下 build.gradle 文件
buildscript {
...
dependencies {
...
classpath "com.google.dagger:hilt-android-gradle-plugin:2.28.3-alpha"
}
}
- 在项目的应用级目录下
...
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'
android {
...
}
dependencies {
implementation "com.google.dagger:hilt-android:2.28-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}
Hilt 使用Java8的功能,所以我们在项目中启用它,应用模块下 build.gradle 文件添加代码。
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// For Kotlin projects
kotlinOptions {
jvmTarget = "1.8"
}
}
注意
在 Kotlin 项目中,需要添加 kotlinOptions,否则ViewModel会编译不通过。
需要注意使用hilt 和data binding,需要AndroidStudio的版本必须>=4.0。
Application 是 App 的入口,所有使用Hilt的App必须包含一个使用@HiltAndroidApp注解的Application
@HiltAndroidApp
class HiltApplication : Application() {
/**
* 1. 所有使用 Hilt 的 App 必须包含一个使用 @HiltAndroidApp 注解的 Application
* 2. @HiltAndroidApp 将会触发 Hilt 代码的生成,包括用作应用程序依赖项容器的基类
* 3. 生成的 Hilt 组件依附于 Application 的生命周期,它也是 App 的父组件,提供其他组件访问的依赖
* 4. 在 Application 中设置好 @HiltAndroidApp 之后,就可以使用 Hilt 提供的组件了,
* Hilt 提供的 @AndroidEntryPoint 注解用于提供 Android 类的依赖(Activity、Fragment、View、Service、BroadcastReceiver)等等
* Application 使用 @HiltAndroidApp 注解
*/
}
- @HiltAndroidApp会触发Hilt代码的生成,包括用作应用程序依赖容器的基类
- 生成的Hilt组件依附于Application的生命周期,它也是App的父组件,提供其他组件访问的依赖。
使用 Hilt 进行依赖注入
注入 HiltSimple 并在 Application 中调用它的doSomething方法。
class HiltSimple @Inject constructor() {
fun doSomething() {
Log.e(TAG, "----doSomething----")
}
}
@HiltAndroidApp
class HiltApplication : Application() {
@Inject
lateinit var mHiltSimple: HiltSimple
override fun onCreate() {
super.onCreate()
mHiltSimple.doSomething()
}
}
Hilt 需要知道如何从相对应的组件中提供必要的依赖实例。使用@Inject注解来告诉Hilt如何提供该类的实例,@Inject 常用于构造函数、非私有字段、方法。
Hilt 常用注解的含义
@HiltAndroidApp
1 所有使用HIlt的App必须包含一个使用@HiltAndroidApp注解的Application。
2 @HiltAndroidApp注解将会触发Hilt代码的生成,作为应用程序依赖项容器的基类。
3 生成的Hilt组件依附于Application的生命周期,它也是App的父组件,提供其他组件访问的依赖。
4 在Application中设置号@HiltAndroidApp之后,就可以使用Hilt提供的组件了,组件包含Applicaiton、Activity、Fragment等。
@AndroidEntryPoint
Hilt 提供的@AndroidEntryPoint注解用于提供Android类的依赖(Activity、Fragment、View、Service、BroadcastReceiver)
特殊的Application使用 @HiltAndroidApp注解。
Activity:支持ComponentActivity的子类例如FragmentActivity、AppCompatActivity等。
Fragment:支持 androidx.Fragment包下的Fragment。
View
Service
BroadcastReceiver
注意
在使用@AndroidEntryPoint在非ComponentActivity子类上注解,例如Activity则会抛出异常。
Activities annotated with @AndroidEntryPoint must be a subclass of androidx.activity.ComponentActivity. (e.g. FragmentActivity, AppCompatActivity, etc.)
使用@AndroidEntryPoint注解时,必须在它的依赖的Android类添加同样的注解,例如Fragment中添加@AndroidEntryPoint注解,必须在Fragment依赖的Activity上也添加@AndroidEntryPoint注解,否则会抛出一样。
java.lang.IllegalStateException: Hilt Fragments must be attached to an @AndroidEntryPoint Activity. Found: class com.hi.dhl.hilt.MainActivity
@Module
常用于创建依赖类的对象(例如第三方库 OkHttp、Retrofit等等),使用@Module注解的类,需要使用@InstallIn注解指定范围module。
@Module
@InstallIn(ApplicationComponent::class)
// 这里使用了 ApplicationComponent,因此 NetworkModule 绑定到 Application 的生命周期。
object NetworkModule {
}
@InstallIn
使用@Module注入的类,使用@InstallIn注解指定module的范围,例如使用@InstallIn(ActivityComponent::class)注解的module会绑定到Activity的生命周期上。
Hilt 提供了以下组件来绑定依赖与对应的Android类的活动范围。
Hilt 提供组件 | 对应的Android类活动范围 | 作用域 |
---|---|---|
ApplicationComponent | Application | @Singleton |
ActivityRetainedComponent | ViewModel | @ActivityRetainedScope |
ActivityComponent | Activity | @ActivityScoped |
FragmentComponent | Fragment | @FragmentScoped |
ViewComponent | View | @ViewScoped |
ViewWithFragmentComponent | View annotated with @WithFragmentBindings | @ViewScoped |
ServiceComponent | Service | @ServiceScoped |
注意
Hilt 没有为 broadcast receivers 提供组件,因为Hilt直接从ApplicationComponent注入broadcast receivers。
Hilt 会根据相应的 Android 类生命周期自动创建和销毁生成的组件类的实例。如下。
Hilt 提供的组件 | 创建对应的生命周期 | 销毁对应的生命周期 |
---|---|---|
ApplicationComponent | Application#onCreate() | Application#onDestory() |
ActivityRetainedComponent | Activity#onCreate() | Activity#onDestroy() |
ActivityComponent | Activity#onCreate() | Activity#OnDestroy() |
FragmentComponent | Fragment#OnAttach() | Fragment#onDestroy() |
ViewComponent | View#super() | View destroyed |
ViewWithFragmentComponent | View#super() | View destroyed |
ServiceComponent | Service#onCreate() | Service#onDestroy() |
@Provides
常用于被 @Module 注解标记类的内部方法,并提供依赖项对象。
@Module
@InstallIn(ApplicationComponent::class)
// 这里使用了 ApplicationComponent,因此 NetworkModule 绑定到 Application 的生命周期。
object NetworkModule {
/**
* @Provides 常用于被 @Module 注解标记类的内部的方法,并提供依赖项对象。
* @Singleton 提供单例
*/
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.build()
}
}
Hilt 同 第三方组件一起使用
如果你要在项目中添加第三方依赖,需要使用@Module注解,使用@Module注解的普通类,在其中创建第三方依赖的对象。
@Module
@InstallIn(ApplicationComponent::class)
// 这里使用了 ApplicationComponent,因此 NetworkModule 绑定到 Application 的生命周期。
object NetworkModule {
/**
* @Provides 常用于被 @Module 注解标记类的内部的方法,并提供依赖项对象。
* @Singleton 提供单例
*/
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideGitHubService(retrofit: Retrofit): GitHubService {
return retrofit.create(GitHubService::class.java)
}
}
- @Module 常用于创建依赖类对象(如OkHttp、Retrofit等等)。
- 使用 @Module注入的类,需要使用@InstallIn注解指定module的范围,会绑定到Android类对应的生命周期上。
- @Provides 常用于标记类的内部方法,并提供依赖项对象。
当需要上下文是使用的注解(预定义限定符)
HIlt提供了预定义限定符。例如,当你需要使用应用或者Activity的Context类时,Hilt提供了@ApplicationContext和@ActivityContext限定符。
假如,当前这个类需要Activity的上下文。
class Test @Inject constructor(
@ActivityContext private val context: Context,
private val service: AnalyticsService
) { ... }