Hilt用使用及原理

what is hilt?

Hilt是基于Dagger构建而成的依赖注入框架,它提供了一种将Dagger纳入Android应用的标准方法:使用Hilt提供的规范来实现依赖注入,可以避免很多不必要的问题。


使用Hilt快速实现依赖注入

根目录 build.gradle.kts(项目根)、app/build.gradle.kts(模块)

先在根插件声明,apply false,子模块按需引入

Kotlin 复制代码
plugins {
    id("com.google.dagger.hilt.android") version "2.57.1" apply false
    id("com.google.devtools.ksp") version "2.0.21-1.0.28" apply false
}
Kotlin 复制代码
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("com.google.devtools.ksp")
    id("com.google.dagger.hilt.android")
}

android {
    namespace = "com.motionguardian.hiltdemo"
    compileSdk = 36

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {
    implementation("com.google.dagger:hilt-android:2.57.1")
    ksp("com.google.dagger:hilt-android-compiler:2.57.1")
}

Application 入口

Kotlin 复制代码
package com.motionguardian.hiltdemo

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class MyApp : Application()

@HiltAndroidApp 标记全局根容器,KSP 编译期自动生成 Hilt_MyApp。 必须在AndroidManifest.xml 注册:

XML 复制代码
<application
    android:name=".MyApp"
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name">

待注入类 User

Kotlin 复制代码
package com.motionguardian.hiltdemo

import javax.inject.Inject

class User @Inject constructor()
  • @Inject constructor() 标记构造函数,告诉 Hilt:这个类无参构造,Hilt 可以自己 new。
  • 只要构造带@Inject,不需要写 Module 就能直接提供实例。

Activity 注入

Kotlin 复制代码
package com.motionguardian.hiltdemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var user: User

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // super.onCreate 走完之后,user 已经被Hilt赋值完成
    }
}

注解说明:

  1. @AndroidEntryPoint:这个 Activity 开启 Hilt 注入能力,Hilt 为此 Activity 生成注入代码。Activity/Fragment/Service 都要加这个注解。
  2. @Inject lateinit var user: User:字段注入声明,Hilt 自动赋值。

Kotlin 这里必须 lateinit var,不能用 val,因为是 Hilt 在 super 之后赋值。不能 private。


Hilt的作用


在Hilt中使用Moudle

Kotlin 复制代码
package com.dongnaoedu.hilt

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import javax.inject.Singleton

@Module
@InstallIn(ApplicationComponent::class)
object AppModule {

    @Singleton
    @Provides
    fun provideUser(): User {
        return User()
    }
}

逐个注解解释:

  1. @Module 标记这个类是 Hilt 模块。模块的作用:告诉 Hilt,这里有创建对象的方法 。 什么时候必须写 Module:要提供的类,不能直接写 @Inject constructor() 的时候。 比如:第三方 SDK 的类、系统类、构造参数很多、需要传配置。 像刚才简单的User如果可以写@Inject constructor(),就不需要这个 Module。
  2. @Provides 写在方法上面,这个方法就是造对象的工厂方法。 Hilt 需要 User 对象的时候,就自动执行这个方法,拿到返回的 User 实例。
  3. @InstallIn(ApplicationComponent.class) 意思:把这个模块安装到全局根容器里面 。ApplicationComponent就是@HiltAndroidApp生成出来的那个全局仓库。 安装在这里,意味着这个模块提供的对象,生命周期和整个 App 进程一致。
  4. @Singleton 单例注解。 在同一个 Component(这里就是 ApplicationComponent)范围内,Hilt 只会调用一次provideUser(),全程共用同一个 User 对象。

组件与作用域的关系

Hilt 组件(仓库) 对应的宿主 作用域注解 对象生命周期
ApplicationComponent Application @Singleton 整个 App 进程存活,App 不杀,对象就一直是同一个
ActivityRetainedComponent ViewModel @ActivityRetainedScope 和 ViewModel 同生命周期,配置变更(旋转屏幕)不会销毁;Activity 真正关闭才销毁
ActivityComponent Activity @ActivityScoped Activity 打开时创建,Activity finish 销毁,页面重新打开就换新对象
FragmentComponent Fragment @FragmentScoped Fragment 创建到 Fragment 销毁
ViewComponent View @ViewScoped View 创建到 View 被移除
ViewWithFragmentComponent 绑定 Fragment 的 View @ViewScoped 同上
ServiceComponent Service @ServiceScoped Service 启动到 Service 停止
  • Component(组件,仓库):容器,是一个存放依赖对象的空间。@InstallIn 就是选择把 Module 放进哪一个仓库。
  • Scope(作用域注解):写在@Provides方法或者@Inject constructor类上面。

Scope 注解必须和 Install 进去的 Component 匹配,不能乱搭配


预定义绑定

预定义绑定 = Hilt 已经提前帮我们写好的 @Provides,我们不用自己写 Module,直接拿来注入。 Hilt 内置把 Android 系统常用对象,提前注册进对应 Component 仓库里了。

可以直接注入的类型 来自哪个 Component
Application ApplicationComponent
Activity ActivityComponent
Context(Activity 上下文) ActivityComponent
Context(Application 上下文) ApplicationComponent
Fragment FragmentComponent
View ViewComponent
Service ServiceComponent

有两个 Context 预定义绑定:

  1. Application Context(全局上下文,不会泄漏):属于 ApplicationComponent
  2. Activity Context(页面上下文,持有 Activity):属于 ActivityComponent

如果直接注入 Context,Hilt 会分不清你要哪一个,这时候就需要 限定符(Qualifier)。


限定符 Qualifier

限定符:给同一个类型打上标签,用来区分同类型多个不同的绑定。

Hilt 自带两个内置限定符:

  • @ApplicationContext:标记全局 Application 上下文
  • @ActivityContext:标记 Activity 上下文
相关推荐
深度学习04072 小时前
MySQL InnoDB Cluster 部署完整文档
android·mysql·adb
邪修king3 小时前
Re:Linux系统篇(三十七):进程间通信Chapter4:System V 共享内存深度解析:为什么它是最快的 IPC?
android·linux·运维
用户337922545683 小时前
Kiora SDK:在 Android 上组织端侧模型、工具与 A2A 协作
android
洞见前行3 小时前
你在 XML 时代学的渲染优化,进了 Compose 大多不再是重点——Recomposition 才是新的战场
android
ii_best4 小时前
按键精灵手机助手 v5.2.1 实测:inputText 逐字延时 + 调试面板多行复制,安卓脚本开发的两个输入痛点一次解决
android·开发语言·智能手机·自动化·ai编程·按键精灵
hunterandroid4 小时前
OkHttp 源码解析:拦截器链、连接池与缓存策略的设计精髓
android
蒲公英内测分发4 小时前
智能手环出海测试,海外合作方分散在不同国家,Android 测试包怎么持续分发和更新?
android·前端·人工智能·测试工具·智能手表
朱涛的自习室4 小时前
高价软件已死,我让 AI 开启了「平替计划」(Day 7 / 7)
android·前端·github