Hilt高级用法全面解析

1,179 阅读3分钟

前言

上一篇文章我们说了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原理的时候再进行补充。