【Android Jetpack】Hilt的理解与浅析

news2025/1/19 7:49:59

文章目录

    • 依赖注入
    • 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/1228330.html

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

相关文章

文档向量化工具(一):Apache Tika介绍

Apache Tika是什么?能干什么? Apache Tika是一个内容分析工具包。 该工具包可以从一千多种不同的文件类型(如PPT、XLS和PDF)中检测并提取元数据和文本。 所有这些文件类型都可以通过同一个接口进行解析,这使得Tika在…

node实战——koa实现文件上传

文章目录 ⭐前言⭐koa实现文件上传⭐foxapi测试⭐总结⭐结束⭐前言 大家好,我是yma16,本文分享关于node实战——node实战——koa实现文件上传。 本文适用对象:前端初学者转node方向,在校大学生,即将毕业的同学,计算机爱好者。 node系列往期文章 node_windows环境变量配置…

Day35力扣打卡

打卡记录 相邻字符不同的最长路径(树状DP) 链接 若节点也存在父节点的情况下,传入父节点参数,若是遍历到父节点,直接循环里 continue。 class Solution:def longestPath(self, parent: List[int], s: str) -> in…

《微信小程序开发从入门到实战》学习二十

3.3 开发创建投票页面 3.3.8 使用icon图标文件 原来已经实现了投票选项的增加和修改功能,现在还差删除。现在为每一个选项增加删除按钮,可以以通过icon图标组件实现。 icon常用属性如下: type icon的类型,有success、s…

Linux虚拟机中网络连接的三种方式

Linux 虚拟机中网络连接的三种方式 先假设一个场景,在教室中有三个人:张三、李四和王五(这三个人每人有一台主机),他们三个同处于一个网段中(192.169.0.XX),也就是说他们三个之间可…

ICASSP2023年SPGC多语言AD检测的论文总结

文章目录 引言正文AbstractRelated ArticleNo.1: CONSEN: COMPLEMENTARY AND SIMULTANEOUS ENSEMBLE FOR ALZHEIMERSDISEASE DETECTION AND MMSE SCORE PREDICTION特征相关模型结构数据处理结果分析 No.2: CROSS-LINGUAL TRANSFER LEARNING FOR ALZHEIMERS DETECTION FROM SPON…

NSS [鹤城杯 2021]Middle magic

NSS [鹤城杯 2021]Middle magic 源码直接给了。 粗略一看&#xff0c;一共三个关卡 先看第一关&#xff1a; if(isset($_GET[aaa]) && strlen($_GET[aaa]) < 20){$aaa preg_replace(/^(.*)level(.*)$/, ${1}<!-- filtered -->${2}, $_GET[aaa]);if(preg_m…

开源与闭源:大模型发展的双重走向

目录 前言开源和闭源的优劣势比较开源的优势闭源的优势 开源和闭源对大模型技术发展的影响对技术发展的影响对数据共享的影响对业务拓展的影响 开源与闭源的商业模式比较开源的商业模式闭源的商业模式 处在大模型洪流中&#xff0c;向何处去&#xff1f;结语 前言 随着人工智能…

【Flink】核心概念:任务槽(Task Slots)

任务槽 每个 worker&#xff08;TaskManager&#xff09;都是一个 JVM 进程&#xff0c;可以在单独的线程中执行一个或多个 subtask。为了控制一个 TaskManager 中接受多少个 task&#xff0c;就有了所谓的 task slots&#xff08;至少一个&#xff09;。 每个任务槽&#xf…

H110主板搭配魔改QNCW升级小记

最近搬家完毕&#xff0c;翻出来一块闲置已久的qncw&#xff0c;隐约记得是买的主板套装&#xff0c;现在主板早已不知踪影&#xff0c;剩下孤零零一个CPU&#xff0c;一起翻出来一个G3900T亮机CPU&#xff0c;应该是同时代的产物。 qncw百度上一搜&#xff0c;发现参数还行&am…

CICD 持续集成与持续交付——jenkins

部署 软件下载&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/ [rootcicd2 ~]# rpm -ivh jdk-11.0.15_linux-x64_bin.rpm[rootcicd2 ~]# yum install -y fontconfig[rootcicd2 ~]# rpm -ivh jenkins-2.432-1.1.noarch.rpm启动服务 [rootcicd2 ~]# systemctl…

【Java】网络编程基础—InetAddress类和URL编程

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;Java ⭐每日一句&#xff1a;为了那个远方&#xff0c;你要奋不顾身 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️ 文章目录 一.&#x…

Python编程技巧 – 使用字符串(Strings)

Python编程技巧 – 使用字符串&#xff08;Strings) Python Programming Essentials – Using Strings 本文简要介绍如何使用字符串&#xff0c;来进行Python编程。字符串有很多用途&#xff0c;包括输出结果、反馈状态、数据处理以及切片和文本筛选等 1. 字符串 字符串(St…

DevToys:开发者的多功能瑞士军刀,让编程更高效!

DevToys&#xff1a;开发者的多功能瑞士军刀&#xff0c;让编程更高效&#xff01; DevToys 是一款专为开发者设计的实用工具&#xff0c;它能够帮助用户完成日常的开发任务&#xff0c;如格式化 JSON、比较文本和测试正则表达式&#xff08;RegExp&#xff09;。它的优势在于…

开源WIFI继电器之硬件电路

一、原理图 源文件 二、原理图说明 1、器件说明 U4&#xff1a;ESP8285模块 U6&#xff1a;触发器 U3&#xff1a;继电器 2、继电器状态检测说明 检测继电器线圈是否通电来判断继电器是否导通&#xff0c;当Q1不导通时&#xff0c;Q1集电极的电压为3.3V&#xff0c;经…

微机原理练习题_13

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案。&#xff09; 1、十六进制数5BF.C8转换成二进制数是(&#xff09; A. 11011100111111101B B. 010111011011.01101B C. 010110111111.11001B D. 010111011011.11001B 2,最适合…

nodejs+vue慢性胃炎健康管理系统的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于慢性胃炎健康管理系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了慢性胃炎健康管理系统&#xff0c; 系统首页、个…

【Android】使用Retrofit2发送异步网络请求的简单案例

添加网络权限到AndroidManifest.xml清单文件 为了让你的Android应用程序能够使用互联网进行通信&#xff0c;你需要在AndroidManifest.xml文件中添加网络权限声明。<uses-permission android:name"android.permission.INTERNET"/> 这个权限应该添加到 Android…

【LeetCode每日一题合集】2023.9.25-2023.10.1(⭐LFU缓存Java数据流花期内花的数量)

文章目录 460. LFU 缓存⭐&#xff08;数据结构题&#xff09;解法1——平衡树 哈希表&#xff08;TreeSet HashMap&#xff09; O ( l o g n ) O(logn) O(logn)解法2——双哈希表 双向链表 O ( 1 ) O(1) O(1) &#xff08;LRU缓存的升级版&#xff09; 2582. 递枕头解法—…

【WSL/WSL2-Ubuntu】突破界限:不使用服务器在一台Windows搭建Nginx+FastDFS

打造超级开发环境&#xff1a;Nginx和FastDFS在WSL中的完美结合 前言 随着软件开发领域的快速发展&#xff0c;跨平台的开发环境变得日益重要。Windows Subsystem for Linux&#xff08;WSL&#xff09;和WSL 2为开发者提供了在Windows操作系统上体验Linux环境的便捷途径。本…