5. 【浅入深出理解 dagger、Hilt】 - Hilt进阶之MVVM

该章站在企业项目角度上如何在MVVM框架上完善并且合理的使用Hilt。

所以如果没了解MVVM的结构建议可以直接忽略这章。大家知道,MVVM里面View和Model之间有关联,假设一个场景View触发一个点击事件调用Model查询,然后Model会调用相关Http类进行查询,返回数据给Model,Model再返回数据给View。
当然上述表达的不是严格意义的MVVM,但是流程相仿,主要是讲解如何注解Model和相关Http类,让他们自动生成

让我们先看看有哪些类


image.png
类名 解释
MyApplication app的入口
MainActivity 顾名思义就是展示的View
ViewModel MainActivity对应的ViewModel,也是MVVM中的Model
TestApi 一个仿造Http的类,只是单纯返回一个数据
NetworkModule 一个制造类,Hilt通过标记自动寻找相关类,然后会找到该类调用相关函数实例化TestApi

那么让我们直接快速讲解

1. 在Project的build.gradle添加引入
    dependencies {
        ...
        classpath "com.google.dagger:hilt-android-gradle-plugin:2.36"
    }
2. 在module的build.gradle分别两处地方添加
plugins {
    ...
    id 'kotlin-kapt'
    id 'dagger.hilt.android.plugin'
}
dependencies {
    ……

    implementation "com.google.dagger:hilt-android:2.37"
    kapt "com.google.dagger:hilt-android-compiler:2.37"
}

好了!添加相关插件自动下载后,我们继续!

3. HiltAndroidApp标记Application
@HiltAndroidApp
class MyApplication : Application()

跟dagger有点不一样的是,必须包含一个带有 @HiltAndroidApp标记的Application类。
当然,别忘记修改AndroidManifest.xml


5. Activity
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: ViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.tvName.append(viewModel.shopBanner.toString())
    }
}

大家看到viewModel就很奇怪,没有标记就能自动生成使用了?其实by viewModels()就已经代表Hilt生成处理了。让我们往下看

4. 创建一个仿造访问网络数据的TestApi 类
class TestApi {
    fun getValue(): Int {
        return 1
    }
}

只是一个简单的创建返回数据类

5. ViewModel

可以同时看到两个标记@HiltViewModel@Inject,那么TestApi在哪里实例化呢?Activity也没有创建TestApi呀,这就是Hilt方便的地方,让我们看下一个NetworkModule

@HiltViewModel
class ViewModel @Inject constructor(
    testApi: TestApi
) : ViewModel() {

    val shopBanner = testApi.getValue()
}
6. NetworkModule

通过@Module@InstallIn@Provides@Singleton等多个标记,让Hilt寻找TestApi的构造方法的时候,找到这里,并且调用GetApi方法创建实例。

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    @Singleton
    fun GetApi(): TestApi {
        return TestApi()
    }

}
7. End

基本就结束了,那么大家很奇怪,其实很简单两句话代码放在MainActivity直接实例化不就行了吗,其实不是这样的,当项目越庞大的时候,可能改变构造函数的时候,那么我们使用Hilt就能很方便的集中在类似NetworkModule这样的类处理,而在Activity这些类中,我们是不需要关心构造函数的。如果你觉得理解还抽象,那么建议先用平常方式写Mvvm,最后再用Hilt优化这方面,或许会有更深入的理解呢!

标记符讲解表格

标记符 标记是为了什么
@Module 标记一个module,代表提供一些无法用构造@Inject的依赖, 比如接口, 第三方库类型, Builder模式构造的对象等
@InstallIn 委托Hilt帮我们管理范围,以管理对象的生命周期,通过指定 Hilt 组件告诉 Hilt 绑定在哪些容器中可用,有很多种容器具体可以看图1
@Provides 提供实例,注释函数,以告诉 Hilt 如何提供无法注入构造函数的 类型
@ViewModelScoped 当在ViewModel中引入协程,如果直接使用CoroutineScope,那么需要在onCleared()方法中取消协程,如果忘记取消协程那么会导致出现内存泄漏等各种问题,此时需要使用ViewModel扩展属性viewModelScope来实现协程作用域

作用域

图1

只是简单介绍依赖注入使用方式的实例源码如下:
zhongjhATC/HiltAndDaggerDemo: 演示 Hilt、Dagger 的demo (github.com)

其他相关文章
1. 【浅入深出理解 dagger、Hilt】 - 简介 - (jianshu.com)
2. 【浅入深出理解 dagger、Hilt】 - dagger无参依赖注入 - (jianshu.com)
3. 【浅入深出理解 dagger、Hilt】 - dagger有参依赖注入 - (jianshu.com)
4. 【浅入深出理解 dagger、Hilt】 - Hilt - (jianshu.com)
在 Android 应用中使用 Hilt | Google Developers

你可能感兴趣的:(5. 【浅入深出理解 dagger、Hilt】 - Hilt进阶之MVVM)