【Android Jetpack】Hilt 依赖注入框架

news2024/11/25 9:33:17

文章目录

    • 依赖注入
    • Dagger
    • Hilt
    • Koin
    • 添加依赖项
    • Hilt常用注解的含义
      • @HiltAndroidApp
      • @AndroidEntryPoint
      • @Inject
      • @Module
      • @InstallIn
      • @Provides
      • @EntryPoint
    • Hilt组件生命周期和作用域
    • 如何使用 Hilt 进行依赖注入

依赖注入

依赖注入是一种软件设计模式,它允许客户端从外部源获取其依赖项,而不是自己创建它们。它是一种用于在对象及其依赖项之间实现控制反转 (IoC) 的技术。

在安卓开发中,依赖注入(Dependency Injection,简称DI)是一种设计模式,用于解耦组件之间的依赖关系。它的基本思想是将对象的依赖关系从代码中移除,而是通过外部容器来管理和注入这些依赖。

传统的方式是在类内部直接创建和管理依赖对象,这样容易导致代码的耦合性增加,难以进行单元测试和代码重用。而依赖注入通过将依赖的创建和管理交给外部容器,使得类只关注自身的逻辑,而不需要关心依赖对象的创建和维护。

Dagger

Dagger是一个Java和Android平台上的依赖注入框架,由Google开发和维护。它的目标是简化管理对象之间的依赖关系,提高代码的可测试性、可扩展性和可维护性。

Dagger基于Java的注解处理器和反射机制,通过在编译时生成依赖注入代码,而不是在运行时进行反射。这种方式具有更好的性能和类型安全性,并且可以在编译时检测到一些错误,提供更好的开发体验。

Dagger是匕首的意思,依赖注入就好像是把匕首直接插入了需要注入的地方,直击要害。

Hilt

Hilt是刀把的意思,它把匕首最锋利的地方隐藏了起来,因为如果你用不好匕首的话反而可能会误伤自己。Hilt给你提供了一个安稳的把手,确保你可以安全简单地使用。

Android团队在Jetpack中增加了HiltHilt是基于Dagger的一个高级封装,旨在简化在Android应用中使用Dagger进行依赖注入的过程。Hilt提供了一套注解和工具,使得使用Dagger更加便捷和易于理解,并且提供了一些默认的配置,以减少开发者的配置工作量。并且得到了 Android Studio 的支持。

Hilt做的优化包括:

  1. 无需编写大量的Component代码
  2. Scope也会与Component自动绑定
  3. 预定义绑定,例如Application和Activity
  4. 预定义的限定符,例如@ApplicationContext@ActivityContext

类似于Room等jetpack,利用注解功能简化了很多复杂的程序。

Hilt的核心思想仍然是依赖注入,它遵循了Dagger的注入原理和组件机制。Hilt的组件体系与Dagger类似,包括ApplicationComponent、ActivityComponent、FragmentComponent等,每个组件都有自己的生命周期和作用域。开发者可以使用Hilt的注解来标记和配置这些组件,以及在需要注入依赖的地方使用相应的注解

Koin

Koin - a smart Kotlin injection library to keep you focused on your app, not on your tools

Koin是为Kotlin开发者提供的一个实用型轻量级依赖注入框架,采用纯 Kotlin 语言编写而成,仅使用功能解析,无代理、无代码生成、无反射。

Hilt、Dagger、Koin等等都是依赖注入库,Google也在努力不断的完善依赖注入库从Dagger到Dagger2在到现在的Hilt,因为依赖注入是面向对象设计中最好的架构模式之一,使用依赖注入库有以下优点:

  • 依赖注入库会自动释放不再使用的对象,减少资源的过度使用。
  • 在配置scopes范围内,可重用依赖项和创建的实例,提高代码的可重用性,减少了很多模板代码。
  • 代码变得更具可读性。
  • 易于构建对象。
  • 编写低耦合代码,更容易测试。

添加依赖项

首先,将 hilt-android-gradle-plugin 插件添加到项目的根级 build.gradle 文件中:

buildscript {
    ...
    dependencies {
        ...
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
    }
}

然后,应用 Gradle 插件并在 app/build.gradle 文件中添加以下依赖项:

...
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

android {
    ...
}

dependencies {
    implementation "com.google.dagger:hilt-android:2.28-alpha"
    kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}

Hilt常用注解的含义

Hilt常用注解包含@HiltAndroidApp@AndroidEntryPoint@Inject@Module@InstallIn@Provides@EntryPoint等等。

@HiltAndroidApp

  1. 所有使用Hilt的App必须包含一个使用@HiltAndroidApp注解的Application。它会替代Dagger中的AppComponent。
  2. @HiltAndroidApp注解将会触发Hilt代码的生成,作为应用程序依赖项容器的基类。
  3. 生成的Hilt组件依附于Application的生命周期,它也是App的父组件,提供其他组件访问的依赖。
  4. 在Application中设置好@HiltAndroidApp之后,就可以使用Hilt提供的组件了,组件包含Application、Activity、Fragment、View、Service、BroadcastReceiver 等等。

@AndroidEntryPoint

Hilt提供的@AndroidEntryPoint注解用于提供Android类的依赖(Activity、Fragment、View、Service、BroadcastReceiver)。

  • Activity:仅仅支持ComponentActivity的子类例如FragmentActivity、AppCompatActivity等等。
  • Fragment:仅仅支持继承androidx.Fragment的Fragment
  • View
  • Service
  • BroadcastReceiver

如果您使用@AndroidEntryPoint为某个Android类添加注释,则还必须为依赖于该类的Android类添加注释。例如,如果您为某个Fragment添加注释,则还必须为使用该Fragment的所有Activity添加注释。

@Inject

Hilt需要知道如何从相应的组件中提供必要依赖的实例。使用@Inject注解来告诉Hilt如何提供该类的实例,它常用于构造函数、非私有字段、方法中。

注意:在构建时,Hilt为Android类生成Dagger组件。然后Dagger遍历您的代码并执行以下步骤:

  • 构建并验证依赖关系,确保没有未满足的依赖关系。
  • 生成它在运行时用于创建实际对象及其依赖项的类。
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {

  @Inject lateinit var analytics: AnalyticsAdapter
  ...
}

注意:由Hilt注入的字段不能为私有字段。尝试使用Hilt注入私有字段会导致编译错误。

@Module

有时,类型不能通过构造函数注入。发生这种情况可能有多种原因。例如,您不能通过构造函数注入接口。此外,您也不能通过构造函数注入不归您所有的类型,如来自外部库的类。在这些情况下,您可以使用Hilt模块向Hilt提供绑定信息。

Hilt模块是一个带有@Module注释的类。与Dagger 模块一样,它会告知Hilt如何提供某些类型的实例。与Dagger 模块不同的是,您必须使用@InstallIn为Hilt模块添加注释,以告知Hilt每个模块将用在或安装在哪个Android类中。

常用于创建依赖类的对象(例如第三方库 OkHttp、Retrofit等等),使用@Module注解的类,需要使用@InstallIn注解指定module的范围。

@Module
@InstallIn(ApplicationComponent::class)
// 这里使用了 ApplicationComponent,因此 NetworkModule 绑定到 Application 的生命周期。
object NetworkModule {
}

@InstallIn

使用@Module注入的类,需要使用@InstallIn注解指定module的范围,例如使用 @InstallIn(ActivityComponent::class) 注解的module会绑定到activity的生命周期上。

Hilt提供了以下组件来绑定依赖与对应的Android类的活动范围。

Hilt 提供的组件对应的 Android 类的活动范围
ApplicationComponentApplication
ActivityRetainedComponentViewModel
ActivityComponentActivity
FragmentComponentFragment
ViewComponentView
ViewWithFragmentComponentView annotated with @WithFragmentBindings
ServiceComponentService

注意:Hilt没有为broadcast receivers提供组件,因为Hilt直接从ApplicationComponent注入broadcast receivers。

@Provides

它常用于被@Module注解标记类的内部的方法,并提供依赖项对象。

@Module
@InstallIn(ApplicationComponent::class)
// 这里使用了 ApplicationComponent,因此 NetworkModule 绑定到 Application 的生命周期。
object NetworkModule {

    /**
     * @Provides 常用于被 @Module 注解标记类的内部的方法,并提供依赖项对象。
     * @Singleton 提供单例
     */
    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .build()
    }
}

@EntryPoint

Hilt支持最常见的Android类Application、Activity、Fragment、View、Service、BroadcastReceiver等等,但是您可能需要在Hilt不支持的类中执行依赖注入,在这种情况下可以使用@EntryPoint注解进行创建,Hilt会提供相应的依赖。

Hilt组件生命周期和作用域

image-20231114001440012

image-20231114001540141

如何使用 Hilt 进行依赖注入

我们先来看一个简单的例子,注入HiltSimple并在Application中调用它的方法。

class HiltSimple @Inject constructor() {
    fun test1() {
        Log.e(TAG, "已经创建成功 ")
    }
}

@HiltAndroidApp
class HiltApplication : Application() {
    @Inject
    lateinit var mHiltSimple: HiltSimple

    override fun onCreate() {
        super.onCreate()
        mHiltSimple.doSomething()
    }
}

Hilt需要知道如何从相应的组件中提供必要依赖的实例。使用@Inject注解来告诉Hilt如何提供该类的实例,@Inject常用于构造函数、非私有字段、方法中。

  • 可参考Jetpack新成员,一篇文章带你玩转Hilt和依赖注入

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1267801.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高级IO—poll,epoll,reactor

高级IO—poll,epoll,reactor 文章目录 高级IO—poll,epoll,reactorpoll函数poll函数接口poll服务器 epollepoll的系统调用epoll_createepoll_ctlepoll_wait epoll的工作原理epoll的工作方式水平触发边缘触发 epoll服务器 reactor poll函数 poll函数是一个用于多路复用的系统调…

docker-compose Foxmic dt版

Foxmic dt 版前言 实现企业对资产的基本管理,包含对资产的登记、维修、调拨、转移等基本功能的支持,并提供对资产的耗材、库存进行管理,有完善的组织架构,非常适合中小企业的需求系统整体覆盖了基本的资产管理、合同管理、运维服务、运维服务、数据中心设备管理等多个模块。…

白盒测试 接口测试 自动化测试

一、什么是白盒测试 白盒测试是一种测试策略,这种策略允许我们检查程序的内部结构,对程序的逻辑结构进行检查,从中获取测试数据。白盒测试的对象基本是源程序,所以它又称为结构测试或逻辑驱动测试,白盒测试方法一般分为…

JVM执行引擎以及调优

1.JVM内部的优化逻辑 1.1JVM的执行引擎 javac编译器将Person.java源码文件编译成class文件[我们把这里的编译称为前期编译],交给JVM运行,因为JVM只能认识class字节码文件。同时在不同的操作系统上安装对应版本的JDK,里面包含了各自屏蔽操作…

Linux下Docker 离线安装详细步骤,亲测成功

1.离线原因:公司新创不能使用开元linux,使用了一个变种centOS,致使yum被禁 2.步骤: 2.1 下载docker tar包,下载地址:Index of linux/https://download.docker.com/linux/ 2.2 新建自己的软件目录&am…

数字化转型的核心是数据,还是应用?_光点科技

数字化转型是当今世界各行各业的热门话题。它不仅仅是将传统的业务流程、产品和服务数字化,更是一种全面的业务战略转变。在这个转变过程中,数据和应用都扮演着至关重要的角色。但究竟哪一个是数字化转型的核心?这个问题值得深入探讨。 我们来…

【JavaEE初阶】死锁问题

目录 一、死锁的三种典型场景 1、一个线程,一把锁 2、两个线程,两把锁 3、N个线程,M把锁 死锁,是多线程代码中的一类经典问题。我们知道加锁是能解决线程安全问题的,但是如果加锁的方式不当,就可能产生死…

力扣:185. 部门工资前三高的所有员工(Python3)

题目: 表: Employee ----------------------- | Column Name | Type | ----------------------- | id | int | | name | varchar | | salary | int | | departmentId | int | ----------------------- id 是该表的主键列(具…

Condition 源码解析

Condition 源码解析 文章目录 Condition 源码解析一、Condition二、Condition 源码解读2.1. lock.newCondition() 获取 Condition 对象2.2. condition.await() 阻塞过程2.3. condition.signal() 唤醒过程2.4. condition.await() 被唤醒后 三、总结 一、Condition 在并发情况下…

linux 之iptables

1.iptables防火墙基本介绍 Linux系统的防火墙:IP信息包过滤系统,它实际上由两个组件 netfilter和 iptables 组成。 主要工作在网络层,针对IP数据包。体现在对包内的IP地址、端口、协议等信息的处理上。 iptables由软件包iptables提供的命令…

诊所电子处方范例之配方模板如何添加到处方中操作教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 诊所门诊在开电子处方的时候,如果能使用模板一键导入,则可以节…

8个程序员常用的开发工具,各位老铁请收好!

Chat GPT的升级节奏让人们越来越惊讶的同时,也让大家感觉到了压力,在如此快节奏的互联网世界中,开发人员需要不断学习与更新知识,保持领先地位并高效地交付高质量软件。 无论是集成开发环境 (IDE)、版本控制系统、测试工具、协作…

二阶常系数非齐次线性微分方程:类型二

或 (1) (2) 欧拉公式 (3) 设(3)有特解 是(1)的特解 是(2)的特解 例 : 解 所以其通解为 这是属于上一篇提到的第一种情况 其特解 即 简化 -2a1 a-1/2 原方程特解为 原方程通解为 解法二 将 或 改写为 设是特征方程的k重根&a…

VR特警野外武装仿真虚拟训练实操教学保证训练效果

特警VR模拟仿真训练软件的优势主要体现在以下几个方面: 真实感和沉浸感:通过VR技术,特警可以在虚拟环境中体验真实的训练场景,如人质解救、反恐行动等。这种真实感和沉浸感可以帮助特警更好地理解和适应实际情况,提高训…

双指针算法(题目与答案讲解)

文章目录 题目移动零复写零两数之和N数之和(>2个数) 答案讲解移动零复写零两数之和N数之和 题目 力扣 移动零 1、移动零:题目链接 复写零 2、复写零:题目链接 两数之和 3、两数之和题目链接 N数之和(>2个数) 4、N数之和(三个数、四个数) 三个数:题目链接 四个数题目链接…

el-table合并行

需求: 1、”用户任务“中的”代码“需要按照升序进行排列; 2、”用户任务“中连续的”会签“是共用一个序号,并且序号进行合并 效果 解决方法 列表排序一般是前端传值,后端进行排序。由于后端返回的表格列表没有 序号indexNum …

【华为数通HCIP | 网络工程师】821刷题日记-BFD和VRRP 及重点(2)

个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…

jmeter多个接口测试

针对接口文档,进行对应接口设计,多个接口设计用例需要使用事物控制器。 1.通过登录接口提取sign值 发送一个登录请求,然后通过正则表达式提取该sign值 正则表达式的使用,我稍后会在下一个博文中详细说明,这边就不多说…

算法中的时间复杂度,空间复杂度

一、前言 算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别 衡量不同算法之间的优劣主要是通过时…

量子芯片:引领计算技术的新篇章

量子芯片:引领计算技术的新篇章 引言 随着量子计算的飞速发展,量子芯片作为量子计算机的核心组件,日益受到人们的关注。量子芯片的出现,不仅有望推动计算技术的革新,更将在信息安全、药物研发、金融投资等领域掀起巨大的变革。在本篇博客中,我们将深入探讨量子芯片的原理…