前言
上一篇文章我们说了Hilt的基本用法,包括如何进行依赖注入以及在Android中对几种固定Android类注入的分析,如果没有看上一篇文章可以查看:
Hilt入门 看这一篇就够了!! - 掘金 (juejin.cn)
那本章主要介绍分析一些Hilt的难点解析。
正文
前面我们一直说的Hilt都是Hilt是Android那几种固定的类,比如App,Activity等,使用@HiltApplication和@AndroidEntryPoint这2个注解,但是我们也可以在Hilt不支持的类中注入依赖项,我们来看看如何使用。
在Hilt不支持的类中注入依赖项
比如下面这个类,我想在CustomProvider中获取Programmer实例,由于CustomProvider并不是前一篇文章说的Hilt能使用AndroidEntryPoint注解能修饰的类,所以直接下面写法:
class CustomProvider {
//我在這裏想注入一個實例
@Inject lateinit var mProgrammer: Programmer
fun printInfo(): String{
return mProgrammer.toString()
}
}
会发现肯定无法编译,因为这个类不是Hilt支持的。
这时就需要使用@EntryPoint注解来完成这个需求,@EntryPoint注解可以创建入口点,入口点是由Hilt管理的代码与非由Hilt管理的代码之间的边界。它是代码首次进入Hilt所管理对象的图的位置,入口点允许Hilt使用它并不管理的代码提供关系图中的依赖项。
直白点说,这个就是一个入口点,进入Hilt管理的范围,所以我们定义:
//我在這裏想注入一個實例
@EntryPoint
@InstallIn(ActivityComponent::class)
interface providerEntryPoint{
fun getProgrammer(): Programmer
}
这样就相当于定义了一个入口,来获取一个Programmer类型的对象,那如何访问入口呢,使用EntryPointAccessors函数,直接看代码:
class CustomProvider {
//我在這裏想注入一個實例
@EntryPoint
@InstallIn(ActivityComponent::class)
interface providerEntryPoint{
fun getProgrammer(): Programmer
}
fun printProgrammerInfo(@ActivityContext context: Activity): String{
//这里就可以获得Hilt管理范围内的Programmer对象
val hiltEntryPoint = EntryPointAccessors.fromActivity(context,providerEntryPoint::class.java)
val programmer = hiltEntryPoint.getProgrammer()
return programmer.toString()
}
}
注意这里的参数,应该是组件实例或者充当组件持有者的@AndroidEntryPoint对象,确保这个组件和@InstallIn注解的范围一样。
简单总结一下,在非Android支持的类中,就相当于创建了一个入口点,而这个入口点也需要安装到Android模块中,然后通过这个入口点就可以访问Hilt框架提供的依赖项。
使用Hilt注入ViewModel对象
在使用Jetpack开发中,ViewModel实例是一个非常特殊的存在,因为它保存着的数据不会随着系统配置变化而改变,而且还是跟随界面的生命周期,所以这个ViewModel实例不是随便就可以创建,关于viewModels函数的特殊之处,在之前文章里也有说明
JetPack使用记录之viewModels函数 - 掘金 (juejin.cn)
那如何直接使用Hilt来获取ViewModel对象呢,话不多说,直接开整:
首先添加依赖:
kapt "androidx.hilt:hilt-compiler:1.0.0-alpha01"
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'
注意版本,我现在添加的是1.0.0-alpha01版本,后面会说一下其他版本,然后在ViewModel对象的构造函数中使用@ViewModelInject注解提供一个ViewModel实例即可:
class TestViewModel @ViewModelInject constructor(
) : BaseViewModel(){
var testLiveData: MutableLiveData<Int> = MutableLiveData()
init {
launchOnUI {
while (true){
delay(1000)
testLiveData.value = (1 .. 100).random()
}
}
}
}
然后在带有@AndroidEntryPoint注释的Activity或者Fragment使用by viewModels()即可获取实例:
private val testViewModel: TestViewModel by viewModels()
到这里基本都了解了,但是官方的库更新的很快,后期会有不一样的API,到时候再添加和补充。
总结
其实关于Hilt的使用和原理还是非常多的内容可说,但是大多数都涉及Dagger,所以等后续有时间分析Dagger原理的时候再进行补充。