Jetpack新成员:依赖注入库Hilt
共 3625字,需浏览 8分钟
· 2021-05-12
前言
基于Dagger2
,Hilt
以Android专属DI框架的身份继续完善了Jetpack的布局,本文将主要介绍Hilt
的优点 & 缺点。
定义
基于Dagger(Dagger2),专为Android App打造的依赖注入方案。
特点
它在保留Dagger2的编译时注入的性能优势前提下,简化了注解的使用。同时针对Android框架类进行了优化。
储备知识
在讲解Hilt前先来简单了解依赖注入的各个角色 & 流程。
依赖的需求方:通过构造参数或字段依赖其他实例的角色,一般使用 @Inject
描述依赖的提供方:对被依赖的实例提供实现的角色,如使用 @Provides
描述依赖的注入方:将提供方的实现注入到需求方的角色,如使用 @Component
描述
Hilt的优点
主要包括:
高度封装了框架类的注入 绑定生命周期 预设作用域 Context注入 针对Jetpack组件的支持
优点1:高度封装了框架类的注入
定义应用组件
对于Application,添加@HiltAndroidApp
注解即可告知Hilt生成应用级别的组件,自动实现了依赖注入的起点,免去了Dagger2的手动调用。
@HiltAndroidApp
class MyApplication : Application() {...}
定义Android框架类组件
@AndroidEntryPoint
注解用来为Activity,Fragment,Service等Android框架类生成Hilt组件,省去了定义相应SubComponent的模板处理。
@AndroidEntryPoint
open class BaseActivity() : AppCompatActivity() {...}
优点2:绑定生命周期
@InstallIn
注解可以告知Hilt每个模块将用在或绑定到哪个Android类中。比如指定的value为ApplicationComponent的话将表明该模块在整个应用周期内只会实例化一份,即单例。其他的还有绑定到Activity生命周期的ActivityComponent。
@Module
@InstallIn(ApplicationComponent::class)
class NetworkModule {...}
优点3:预设作用域
@Singleton
和@ActivityRetainedScoped
等注解用以声明该注入的作用范围。比如Activity因为Configuration Change重绘了但@ActivityRetainedScoped注释的依赖的并不会重新创建。
@ActivityRetainedScoped
class MovieAdapter @Inject constructor() { ... }
@AndroidEntryPoint
class DemoActivity : AppCompatActivity() {
@Inject lateinit var movieAdapter: MovieAdapter
...
}
优点4:注入Context
通过@ApplicationContext
和@ActivityContext
注解等可以快速注入Context实例,省得我们自己提供Context的实现。
class MovieAdapter @Inject constructor(@ActivityContext private val context: Context)
: RecyclerView.Adapter<RecyclerView.ViewHolder>() {...}
优点5:Jetpack组件的支持
Hilt实现了一些扩展帮助我们注入ViewModel和WorkManager的依赖。比如@ViewModelInject
注解就可以告知Hilt此处需要注入ViewModel实例。
class MovieViewModel @ViewModelInject constructor(private val repository: Repository,
var movieAdapter: MovieAdapter
) : ViewModel() {...}
Hilt的缺点
主要包括:
@AndroidEntryPoint的限制 Android框架类的注入限制 生命周期限制 ViewModel注入限制
缺点1:@AndroidEntryPoint的限制
@AndroidEntryPoint 的限制 | 限制内容 |
---|---|
依附类 | 依附类的话同样需要添加@AndroidEntryPoint |
Activity | 只能注解ComponentActivity子类Activity |
Fragment | 只能注解androidx的Fragment,但不包括不支持Retained Fragment |
基类 | 基类可统一添加@AndroidEntryPoint,但抽象类不需要 |
缺点2:Android框架类的注入限制
Android框架类的注入限制 | 限制内容 |
---|---|
注入方式 | 只能是字段注入 |
字段的修饰符 | 不能为private |
BrocastReceiver | 不会生成单独的组件 |
View | 默认绑定到ActivityComponent |
ContentProvider | 无法直接使用@AndroidEntryPoint注解 |
缺点3:生命周期的限制
生命周期的注意 | 限制内容 |
---|---|
默认的绑定 | 每次注入都会创建新的实例 |
ActivityRetainedComponent | 最后一次destroy时销毁 |
缺点4:ViewModel注入限制
使用@ViewModelInject向ViewModel注入依赖需要注意:
如果使用 viewModels()
的KTX获取ViewModel实例的话,可能会遇到找不到该KTX的问题,这时候注意下gradle文件有没有导入fragment-ktx
的依赖如果运行失败并提示viewmodel不包含默认构造函数,一定记得检查下 hilt-compiler
的注释处理器有没有在gradle文件里声明如果编译发生如下的错误,需记得在gradle的kotlinOptions里声明jvm的版本为1.8
总结
相较于Dagger2,Hilt确实存在许多优点,但于其同时也带来一些天生的劣势。在实际应用中,「需要根据实际需要做出抉择:小而美的Hilt 抑或是 大而强的Dagger2。」
官方文档
https://developer.android.google.cn/training/dependency-injection/hilt-android
本文来自读者虾米君投稿,其公众号:TechMerger
「Carson每天带你学习一个Android知识点」,长按扫描关注公众号。同时,期待您精彩文章的投稿:真诚邀请您来分享
最后福利:学习资料赠送
福利:由本人亲自撰写 & 整理的「Android学习方法资料」 数量:10名 参与方式:「点击文章右下角”在看“ -> 回复截图到公众号 即可,我将从中随机抽取」 点击“在看”就能升职 & 加薪水哦!