Android Hilt 笔记

本文介绍了Android Hilt的依赖注入原理和使用步骤,包括添加依赖项、使用必要注解以及各种注入方式。虽然Hilt提供了与Jetpack组件的良好集成,但作者建议考虑使用Koin,因其简洁明了。Hilt的优势在于与Android类的原生支持,但完全注解的方式可能导致代码可读性下降和APK体积增大。

官网介绍已经讲解的非常详细了,这里就不做过多的介绍,只是记录下核心的思想和步骤,让应用可以跑起来,并且用到核心的依赖注入功能。(建议不要使用Hilt,去用Koin,Koin比这个Hilt好用太多了,简洁明了。参考:Kotlin替换Dagger2/Hilt的依赖注入框架–Koin

浅谈依赖注入

依赖注入是控制反转的一种实现方式,目的是: 分 离 创 建 这 个 类 的 代 码 和 使 用 这 个 类 的 代 码 分离创建这个类的代码和使用这个类的代码 使
为什么要分离呢?因为:一个类有特别多的依赖时,创建依赖的时候,又会导致其他更多的依赖被创建。这个时候如果不将这些创建代码分离开来,会导致创建逻辑异常复杂、代码极度耦合、测试难度加大等问题。

使用步骤

添加依赖项

如何添加依赖库,参考官方的添加依赖项,这里就不花篇幅讲解了。更全面的设置和最新的版本可以参考Dagger官网的指导。

必要注解

所有使用 Hilt 的应用都必须包含一个带有 @HiltAndroidApp 注释的 Application 类。

@HiltAndroidApp
class HiltApp : Application()

注入方式

hilt应用代码为例,给Activity注入相应依赖:

// 依赖项
data class SimpleData constructor (var name: String)
data class EmunData constructor(val name: String)
interface InterfaceData {
    fun getName(): String
}
class InterfaceDataImpl @Inject constructor() : InterfaceData {
    override fun getName(): String {
        return toString()
    }
}
// 需要被注入依赖项的Android类
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject lateinit var simpleData: SimpleData
    @Inject lateinit var interfaceData: InterfaceData
    @EmunB
    @Inject lateinit var emunData: EmunData
    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val tv = findViewById<TextView>(R.id.tvHint)
        tv.textSize = 20F
        tv.text = simpleData.name +
                "\n${interfaceData.getName()}" +
                "\n$this" +
                "\n${emunData.name}"
    }
}

数据和Android类(点我知道什么是Android类)都已经准备好了,那么我们开始注入数据。

  1. 注入 simpleData:
    可以看到 simpleData 是通过 @Inject 注解来修饰的,这代表它是需要被注入的数据,那么怎么注入呢?注入代码如下:
    @Module
    @InstallIn(ActivityComponent::class)
    object SimpleDataModule {
        @Provides
        fun provideSimpleData(): SimpleData {
            return SimpleData("Name")
        }
    }
    
    注解:
    • @Module:用于标记它是一个用于提供注入的模块类
    • @InstallIn:用于标识这个 @Module 要安装在哪个Android类中(注意 @Module 和 @InstallIn 注解要一起使用)
    • @Provides:用于注入,这个注解会被Hilt自动识别,并为所有的带有 @Inject 的 SimpleData 进行注入
  2. 注入interfaceData:这个数据是一个接口,不过注入注解也是 @Inject。注入代码如下:
    @Module
    @InstallIn(ActivityComponent::class)
    abstract class InterfaceDataModule {
        @Binds
        abstract fun bindInterfaceData(interfaceData: InterfaceDataImpl): InterfaceData
    }
    
    可以看到这个是抽象类,可见是 Hilt 给它进行了实现。Hilt 如何找到这个 bindInterfaceData 方法所需要的参数呢?就是如下的 @Inject 注解告诉了 Hilt 如何给它提供参数。
    class InterfaceDataImpl @Inject constructor() : InterfaceData {
        override fun getName(): String {
            return toString()
        }
    }
    
    注解:
    • @Binds:绑定一个类型到另一个类型的注入方式。这个注解只能修饰抽象方法,且有一个参数和一个返回值对应。上面的例子就是 InterfaceDataImpl 到 InterfaceData 的绑定注入。
  3. 注入 emunData:可以看到这属性多了一个注解 @EmunA,这个是用来给单个数据类型提供多个注入方式的注入方法,注入代码如下:
    @Qualifier
    @Retention(AnnotationRetention.BINARY)
    annotation class EmunA
    @Qualifier
    @Retention(AnnotationRetention.BINARY)
    annotation class EmunB
    @Module
    @InstallIn(SingletonComponent::class)
    class EmunDataModule {
        @EmunA
        @Provides
        fun provideEmunA() = EmunData("EmunA")
        @EmunB
        @Provides
        fun provideEmunB() = EmunData("EmunB")
    }
    
    可以看到只是比给 simpleData 注入的时候多了两个步骤:
    1. 定义 @EmunA 和 @EmunB 两个注解
    2. 给两个 @Provides 修饰的方法分别加上了 @EmunA 和 @EmunB 两个注解
      这两个步骤就可以在注入的时候选择是通过 provideEmunA 方法注入还是通过 provideEmunB 方法注入

总结

至此,Hilt的基本用法已经大致了解了。个人感觉Hilt的优势主要体现在两点上:

  1. 在和其他的Jetpack组件一起使用的时候可以有加成,像生命周期的管理,Android类的原生支持之类的。
  2. 完全由注解来构建依赖关系,不需要额外的代码来构建,加上AndroidStudio的强大跳转支持,可以很快定位到依赖关系。

不过也有些缺点:

  1. 完全使用注解的方式来定位依赖关系,会导致看代码不能知道到底是如何注入的,特别是依赖关系一多,就不是很明了。需要借助AndroidStudio才能快速找到。
  2. 学习注解的成本很大
  3. 会自动生成大量的注入代码,增加APK体积

个人还是觉得Kotlin就用Koin吧!(#.#)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值