携手创作,共同成长!这是我参与「日新计划 8 月更文挑战」的第13天,点击查看活动详情
为什么要运用Hilt依靠注入
之前有写过一些文章 Hilt与Koin的对比,和 Android开发中Hilt的常用场景。看起来是十分简略与实用了,可是会引起一些同学的疑问?
为什么要运用依靠注入?直接new目标不香吗?为什么要把简略的问题杂乱化?
你是不是在炫技,是不是像装13?
这还真不是,假如说我运用的Dagger2,还真是炫技,NB啊。Dagger的坑也是真的多,能在大项目中把Dagger用好,那还真是牛,可是咱们现在都用Hilt了有什么可装的,运用是真的简略,都是一些场景化的东西,一些固定用法。没必要没必要。
回归正题,为什么要运用依靠注入?哪种情况下引荐运用依靠注入?就算要用依靠注入,为什么依靠注入引荐运用Hilt?
一、主动办理(灵活与解耦)
首要不是说咱们写项目就必定要运用依靠注入,假如咱们的项目不是大项目,总共就5、6个,10多个页面,你没必要上依靠注入结构,假如是大项目,分模块,分组件,多人协同开发的,而且或许依靠的目标很杂乱,或者说套娃似的目标依靠,那么运用Hilt就十分便利。不同模块/组件的开发人员直接在他自己的组件/模块下定义好目标的供给方法,另一边直接用即可,无需联系依靠的杂乱度,和完成的逻辑。
咱们先看看一些杂乱的嵌套依靠,比方咱们来一个三层套娃的依靠:
@Singleton
class UserServer @Inject constructor(private val userDao: UserDao) {
fun testUser() {
YYLogUtils.w(userDao.printUser())
toast(userDao.printUser())
}
fun getDaoContent():String{
return userDao.printUser()
}
}
@Singleton
class UserDao @Inject constructor(private val user: UserBean) {
fun printUser(): String {
return user.toString()
}
}
data class UserBean(
val name: String,
val age: Int,
val gender: Int,
val languages: List<String>
)
其他三个类都是有必要了,其实也就多了一个这个类,供给UserBean目标
@Module
@InstallIn(SingletonComponent::class)
class Demo10DIModule {
@Singleton
@Provides
fun provideUser(): UserBean {
return UserBean("newki", 18, 1, listOf("中文", "英文"))
}
}
运用:
@AndroidEntryPoint
class Demo10DIActivity : BaseVMActivity() {
@Inject
lateinit var userServer: UserServer
override fun getLayoutIdRes(): Int = R.layout.activity_demo10_di
override fun init() {
findViewById<Button>(R.id.btn_01).click {
YYLogUtils.w(userServer.toString())
userServer.testUser()
}
}
假如不运用Hilt,自己new目标也能完成
class Demo10DIActivity : BaseVMActivity() {
lateinit var userServer: UserServer
override fun getLayoutIdRes(): Int = R.layout.activity_demo10_di
override fun init() {
//自己new三个目标
userServer = UserServer(UserDao(UserBean("newki", 18, 1, listOf("中文", "英文"))))
findViewById<Button>(R.id.btn_01).click {
YYLogUtils.w(userServer.toString())
userServer.testUser()
}
}
这样new出来的目标,且不说生命周期是跟随页面的,无法保持单例,咱们就说假如需求变了,UseDao中需要UserBean和UserProfile2个目标了,假如你是new目标,那么就要处处修正,假如是Hilt的方法,咱们就只需要修正UserDao目标的构造即可
@Singleton
class UserDao @Inject constructor(private val user: UserBean,private val profile:UserProfile) {
fun printUser(): String {
return user.toString()
}
}
以上仅仅举个简略比方,构建一个目标,还要构建一堆其他的目标,而且其他目标的构建相同杂乱,而且有必要按顺序构建,而且需要的目标的生命周期都不相同,有些生命周期或许和Activity相同,有些或许是单例,所以在构建的时分还要考虑目标声明周期,考虑目标的来历。
特别是在大型项目中很痛苦,由于项目不是一个人写的,咱们协同合作开发,看他人的代码也和看天书相同,并不知道搭档的目标是怎样创立的,假如一个目标的构建方法发生改变,会影响整个的构建过程以及所相关的代码,牵一发而动全身。
这个时分依靠注入结构就派上用场了,咱们只用专心于怎样完成功能,目标的依靠联系和生命周期,都让它来帮咱们办理,一个Inject,它会按照依靠联系帮咱们注入咱们需要的目标,而且它会办理好每个目标的生命周期,在生命周期还没完毕的情况下是不会重复new的。
所以Hilt依靠注入十分适合大项目,小项目开发者由于项目杂乱度低,没遇到这些问题,所以不会了解为什么要用Hilt依靠注入,发出疑问,为什么要让简略的new目标搞这么杂乱。
二、生命周期操控
这里说目标的生命周期,其实便是在必定效果域的生命周期,假如仅仅说单例有点太浅薄,能够说是是在必定规模内的单例。
咱们直接new目标是无法操控生命周期的,除非咱们运用大局单例的目标,而经过Hilt依靠注入咱们能够很便利的完成目标的生命周期的操控。
比方咱们一般目标的快速注入方法,直接注解Singleton就标注的是大局规模单例
@Singleton
class UserServer @Inject constructor(private val userDao: UserDao) {
fun testUser() {
YYLogUtils.w(userDao.printUser())
toast(userDao.printUser())
}
fun getDaoContent():String{
return userDao.printUser()
}
}
另一种用法是咱们运用Module的方法定义依靠注入,那么运用SingletonComponent + Singleton 相同是大局规模单例的意思
@Module
@InstallIn(SingletonComponent::class)
class Demo10DIModule {
@Singleton
@Provides
fun provideUser(): UserBean {
return UserBean("newki", 18, 1, listOf("中文", "英文"))
}
}
假如咱们想Activity内的单例,咱们运用ActivityComponent + ActivityScoped 便是Activity规模的单例。
@Module
@InstallIn(ActivityComponent::class)
class Demo10DIModule {
@ActivityScoped
@Provides
fun provideUser(): UserBean {
return UserBean("newki", 18, 1, listOf("中文", "英文"))
}
}
以上两种都是比较常用的效果域,其他的咱们还能保证Fragment内单例,View内部单例等等,用法都是相同的用法。
所以对依靠目标的生命周期操控也是Hilt很便利的一个特点,运用new目标是无法做到这一点的。
三、对比其他依靠注入
目前Android干流的也便是三种依靠注入 Dagger2 Hilt Koin。
之前比较过Koin,只能在Kotlin言语环境中运用。而且性能并不会好过Hilt。过错提示也不友好。
Dagger2不是不能用,17年18年的时分特别火,可是学习本钱很高,每次创立UI个依靠注入类还得mackproject,而且过错的提示也不友好,
其实我17年就已经在运用Dagger2了,然后自己做了Demo与结构封装,后来做项目中并没有运用,一个是坑太多,一个是搭档不会用,学习本钱太高。也就抛弃运用Dagger2了。
而Hilt其实便是Daggert2的Android场景化的完成,内部对Dagger2进行了封装,在Android开发中运用Hilt愈加的简洁,学习本钱很低,过错提示友好。而且还对ViewModel都能够注入了哦。所以说它是专为Android开发而生。
关于注入的目标内存占用是否有优化的这一点,其实并没有文章或者官方的文档指出有内存优化这一点,仅我自己的测验来说,整个页面假如有多个注入目标和直接new目标比较,感觉注入的目标占用内存稍微少一点,不知道是不是测验的波动,我不了解,如有懂的大佬还望点拨一下。
总结
总结为什么要运用Hilt。
- 偷懒;主动办理,多目标的主动注入,万一有修正不需要到尸山中处处趴。
- 单例;让目标拥有生命周期,无需咱们自己手动单例创立,然后去手动刊出。
- 解耦;不需要处处引进我一些不需要的目标,特别是组件化的项目,另一个组件只管注入,在我的组件中我只管引证。
我觉得这是我运用Hilt最招引我的三个点,
所以说目前2022年了,依靠注入我引荐Hilt。关键运用简略,在Android的常用场景下我还做了一些 Demo, 总共就那么多固定的一些用法,之前我写过Demo掩盖Android开发大部分的运用场景, 有需要直接拿走即可,能够查看我之前的文章。
趁便说一句,这是国外程序员的必备面试技能,感觉比较国内的开发者老外的Android开发者特别喜欢运用Dagger2和Hilt,不少老项目都是用Dagger2的。
好了,本期内容如讲的不到位或讹夺的当地,希望同学们能够指出交流。
假如感觉本文对你有一点点点的启示,还望你能点赞
支撑一下,你的支撑是我最大的动力。
Ok,这一期就此结束。