该章站在企业项目角度上如何在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
<application
android:allowBackup="true"
android:name=".MyApplication"
...
</application>
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
网友评论