hilt依赖注入

他应该满足,只要应用程序存在,那么依赖项就一直存在,并且保持单例模式

添加依赖项

首先,将 hilt-android-gradle-plugin 插件添加到项目的根级 build.gradle 文件中:

1
2
3
4
plugins {
...
id("com.google.dagger.hilt.android") version "2.44" apply false
}

然后,应用 Gradle 插件并在 app/build.gradle 文件中添加以下依赖项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
kotlin("kapt")
id("com.google.dagger.hilt.android")
)
dependences{
//Dagger Hilt
implementation("com.google.dagger:hilt-android:2.44")
kapt("com.google.dagger:hilt-android-compiler:2.44")
//ViewModel Compose
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")

}

// Allow references to generated code
kapt {
correctErrorTypes = true
}

注册Activity,Application

Hilt 应用类

所有使用 Hilt 的应用都必须包含一个带有 @HiltAndroidApp 注解的 Application 类。

@HiltAndroidApp 会触发 Hilt 的代码生成操作,生成的代码包括应用的一个基类,该基类充当应用级依赖项容器。(需要在Manifest中注册)

1
2
@HiltAndroidApp
class ExampleApplication : Application() { ... }

将依赖项注入 Android 类

在 Application 类中设置了 Hilt 且有了应用级组件后,Hilt 可以为带有 @AndroidEntryPoint 注解的其他 Android 类提供依赖项:

1
2
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() { ... }

Hilt 目前支持以下 Android 类:

  • Application(通过使用 @HiltAndroidApp
  • ViewModel(通过使用 @HiltViewModel
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

singleton component vs singleton annotation?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Module
@InstallIn(SingletonComponent::class)
//it means lifetime of our dependencies
object AppModule {

@Provides
@Singleton
//it means all component will use this one object
fun provideMyApi(): MyApi {
return Retrofit.Builder()
.baseUrl("https://zfxt.top")
.build()
.create(MyApi::class.java)
}

}

viewModel

构建一个viewModel带参数时,我们通常需要使用到factory去构建,不然将会很难实现其功能。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MyViewModel(
private val repository: MyRepository
):ViewModel() {


}


//使用注解后
@HiltViewModel
class MyViewModel @Inject constructor(
private val repository: MyRepository
):ViewModel() {

}


//只需要使用viewModel:MyViewModel = viewModel()

AppModule

对于AppModule中相互调用,只需要添加其参数即可自动识别到

对于Module而言,他会根据返回的类型来判断注入方式。如果你对某一个类型有多个返回方法就可能导致程序奔溃,例如你定义了两个providerString1provideString2就会导致程序奔溃

因此,我们需要通过@Named来区分同一类型的对象如何导入

如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

@Provides
@Singleton
fun provideMyApi(): MyApi {
return Retrofit.Builder()
.baseUrl("https://zfxt.top")
.build()
.create(MyApi::class.java)
}

@Provides
@Singleton
fun providerMyRepository(api:MyApi,app:Application,@Named("hello1") hello:String): MyRepository {
return MyRepositoryImpl(api,app)
}

@Provides
@Singleton
@Named("hello1")
fun providerString1()="Hello 1"

@Provides
@Singleton
@Named("hello2")
fun providerString2()="Hello 2"

}

Binding方式

我们可以不适用@Provider的方式提供,而是通过构建一个抽象类和抽象函数来实现,

如下:

  1. 首先为我们的实现类注释@Inject的构造函数方法
1
class MyRepositoryImpl @Inject constructor(...)
  1. 然后创建一个新的抽象类
1
2
3
4
5
6
7
8
9
10
@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {

@Binds
@Singleton
abstract fun bindMyRepository(
myRepository: MyRepositoryImpl
):MyRepository
}

这样子就算实现功能了,他的使用场景通常是无法通过构造函数来构建的时候,在我们使用service的时候,我们就不能通过创建的方式来导入repository。因此我们用@Inject加上Binding的方法实现注入功能

1
2
3
4
5
6
7
@AndroidEntryPoint
class MyService:Service(){
@Inject
liteinit var repository:MyRepository
override fun onBind(po:Intent?):IBinder?
return null
}

Lazy Injection

他会延迟注入,只有在对象被使用到的时候才去注入,

他的使用方法为在类型外包一层Lazy<>即可:如

1
2
3
4
@HiltviewModel
class MyViewModel @Inject constructor(
private val repository:Lazy<MyRepository>
)ViewModel(){