Hilt 是 Android 的依靠项注入库,可减少在项目中执行手动依靠项注入的样板代码。
Android Studio环境为 Android Studio Flamingo | 2022.2.1
Hilt最新版本为2.46
增加Hilt
首先在根目录的build.gradle
中增加Hilt
插件:
plugins {
...
id 'com.google.dagger.hilt.android' version '2.46' apply false
}
然后在app/build.gradle
中增加Hilt
依靠:
plugins {
// kotlin需求增加kapt
id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
}
android {
...
// hilt运用Java 1.8,创立工程默认现已增加
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation "com.google.dagger:hilt-android:2.46"
kapt "com.google.dagger:hilt-compiler:2.46"
}
至此咱们就能够体会Hilt
的功用了。
简单运用Hilt
未运用Hilt之前
在未运用Hilt
之前,假如咱们想要在Activity
中结构一个类,一般的咱们直接运用类的结构办法来创立
class HiltActivity : BaseActivity<ActHiltBinding>() {
private val test = Test()
override fun initViewBinding() = ActHiltBinding.inflate(layoutInflater)
override fun onResume() {
super.onResume()
test.print()
}
}
class Test {
fun print() {
Log.d("Test", "print: Test")
}
}
这是咱们惯例注入一个类的操作,每次都需求运用结构办法来创立目标,然后经过目标来调用其公共办法。
接下来看看运用Hilt
之后怎么来结构一个类
运用Hilt之后
Hilt
要求运用的App
有必要包含一个带有@HiltAndroidApp
注解的Application
类
@HiltAndroidApp
class HiltApplication : Application() {
}
# AndroidManifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:name=".HiltApplication">
</application>
</manifest>
记得在Manifest
中声明咱们自定义的HiltApplication
注入无参目标
假如咱们想在Activity
中运用Hilt
来结构其它类的时分,需求在Activity
类上增加@AndroidEntryPoint
注解,此注解会生成一个单独的Hilt
组件,然后咱们就能够在类中运用@Inject
注解执行注入操作了,具体看下面代码:
/**
* @description
* @author Taonce.
* @date 2023/5/10/22:13
*/
@AndroidEntryPoint
class HiltActivity : BaseActivity<ActHiltBinding>() {
@Inject
lateinit var hiltTest: HiltTest
override fun initViewBinding() = ActHiltBinding.inflate(layoutInflater)
override fun onResume() {
super.onResume()
hiltTest.print()
}
}
class HiltTest @Inject constructor() {
fun print() {
Log.d("HiltTest", "print: HiltTest")
}
}
HiltTest
是一个无参的类,需求在此结构办法之前加上@Inject
,此操作就是告知Hilt
是怎么来创立此目标;
然后在Activity
中就能够运用@Inject lateinit var hiltTest: HiltTest
来声明目标了,目标不能够运用val
关键字,一定要lateinit var
来润饰。
注入有参目标
看完上面这种无参类之后,是不是有个疑问,假如HiltTest
是一个有参结构办法怎么办,Hilt
是不是也能够直接创立呢?答案是否,有参数的结构办法咱们也是需求告知Hilt
此参数怎么来创立,请看下面代码:
@AndroidEntryPoint
class HiltActivity : BaseActivity<ActHiltBinding>() {
@Inject
lateinit var hiltTestParams: HiltTestParams
override fun initViewBinding() = ActHiltBinding.inflate(layoutInflater)
override fun onResume() {
super.onResume()
hiltTestParams.print()
}
}
class HiltTestParams @Inject constructor(
private val params: Params
) {
fun print() {
params.print()
}
}
class Params @Inject constructor() {
fun print() {
Log.d("HiltParams", "print: HiltParams")
}
}
这儿咱们想经过Hilt
帮忙注入一个HiltTestParams
实例,它是一个带有Params
参数的结构办法,而且Params
目标在结构办法之前也加上了@Inject
注解,这样Hilt
就能够一步一步得到所有的信息。
注入三方目标
到这一步咱们能够运用Hilt
来注入自己定义的类,假如咱们想注入三方类咋办呢?咱们不能够直接在三方类的结构办法中加入@Inject
注解呢(或者三方类实例不能够直接运用结构办法来创立)…Hilt
还有一种办法协助咱们注入这种类型的类,下面以Retrofit
举例看看是怎么注入的。
@Module
@InstallIn(ActivityComponent::class)
object RetrofitProvider {
@Provides
fun providerRetrofit(): Api {
return Retrofit.Builder()
.baseUrl("https://www.wanandroid.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(Api::class.java)
}
}
@AndroidEntryPoint
class RetrofitActivity : BaseActivity<ActRetrofitBinding>() {
@Inject
lateinit var api: Api
override fun initViewBinding() = ActRetrofitBinding.inflate(layoutInflater)
override fun onResume() {
super.onResume()
lifecycleScope.launch {
val article = api.article()
Log.d("RetrofitActivity", "Retrofit article: $article")
}
}
}
Hilt
供给了Module
模块协助咱们供给注入的一些信息,它会向Hilt
告知怎么供给某些类型的实例,而且Module
有必要运用@InstallIn
注解来告知Hilt
此模块将效果于哪个Android
类中,@InstallIn
效果于见下图
Hilt 组件 | 注入器面向的目标 |
---|---|
SingletonComponent | Application |
ActivityRetainedComponent | 不适用 |
ViewModelComponent | ViewModel |
ActivityComponent | Activity |
FragmentComponent | Fragment |
ViewComponent | View |
ViewWithFragmentComponent | 带有 @WithFragmentBindings 注解的 View |
ServiceComponent | Service |
providerRetrofit()
办法的回来目标是一个Api
实例,而且办法用@Provides
来注解,此注解就是告知Hilt
每逢需求运用Api
实例的时分,都是经过此办法来注入创立。
注入接口实例
接口是没有办法直接经过结构办法来创立它的实例的,Hilt
供给了@Binds
方式协助咱们住一个一个接口的实例,具体看下面实现代码
interface ApiService {
fun doSomething()
}
class ApiServiceImpl @Inject constructor() : ApiService {
override fun doSomething() {
Log.d("ApiServiceImpl", "doSomething")
}
}
@Module
@InstallIn(SingletonComponent::class)
interface AppModule {
@Binds
fun bindApiService(apiServiceImpl: ApiServiceImpl): ApiService
}
ApiService
是一个接口,bindApiService()
办法协助咱们自动生成它的实例目标,需求经过@Binds
来进行注解,而且传参是它的具体实现实例
经过上述代码咱们就能够直接运用@Inject
来引证此目标了
@AndroidEntryPoint
class InterfaceActivity : BaseActivity<ActHiltBinding>() {
@Inject
lateinit var apiService: ApiService
override fun initViewBinding(): ActHiltBinding {
return ActHiltBinding.inflate(layoutInflater)
}
override fun onResume() {
super.onResume()
apiService.doSomething()
}
}
结尾
导致停止,咱们就能够运用Hilt
来注入一些平常高频的实例,后面会接着阐明Hilt
中限定符和效果域常识。