Hilt 基本使用:@HiltAndroidApp 与 @AndroidEntryPoint

你拿到一个新项目,第一件事是什么?我习惯先把 DI 框架搭好。Hilt 的入口就两个注解:@HiltAndroidApp 和 @AndroidEntryPoint。别小看它们,一个没写对,整个依赖注入链就断了。

1. @HiltAndroidApp —— 应用的根

说白了,这就是 Hilt 的启动开关。你必须把它加到你的 Application 类上,而且只能加一次。我遇到过新手直接在 Activity 上用了 @HiltAndroidApp…… 嗯,编译直接报错。

@HiltAndroidApp
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // 可以在这里做初始化,但别把 Hilt 相关逻辑放这儿
    }
}

这个注解干了三件事:

  • 生成一个 Hilt_MyApplication 基类
  • 触发 Dagger 的 APT 处理器,扫描所有带 @AndroidEntryPoint 的组件
  • 创建顶层 SingletonComponent,管理整个应用的生命周期
个人习惯:我会在 @HiltAndroidApp 的 Application 里初始化一些日志、Crash 上报等非业务模块,但绝不要动 Hilt 生成的任何方法名。记住,Hilt 生成的类名以下划线结尾,比如 Hilt_MyApplication,你不需要手动调用它们。

2. @AndroidEntryPoint —— 组件的门票

每个需要用到注入的 Android 组件,比如 Activity、Fragment、Service,都要贴上这个注解。没有它,Hilt 根本不会碰你的类。我曾经在某个 Fragment 里忘了加,结果运行时空指针满天飞,排查了半天才发现是这个原因。

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject lateinit var repository: MyRepository

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // repository 已经可以用了
    }
}

注意几个关键点:

  • 必须先写 super.onCreate() —— Hilt 在 super 调用里完成了注入,你在这之前访问 @Inject 字段会报错
  • Fragment 中的注入时机是 onAttach() 结束后到 onCreate() 之间,所以你在 onCreate() 里用就已经安全了
  • View、BroadcastReceiver 等组件不支持 @AndroidEntryPoint,需要别的处理方式(以后章节会讲)
我曾经踩过的坑:在 ViewModel 上用了 @AndroidEntryPoint。其实 ViewModel 应该用 @HiltViewModel。当时编译没报错,但运行时根本注不进去。记住:@AndroidEntryPoint 只适用于 Activity、Fragment、Service、BroadcastReceiver,别乱贴。

3. 它们之间的协作流程

先看这张图,你就清楚了:

Hilt 初始化流程 @HiltAndroidApp Application 启动 生成 Hilt_Application AP处理器扫描组件 SingletonComponent 全局依赖容器 @AndroidEntryPoint Activity @AndroidEntryPoint Fragment @AndroidEntryPoint Service 组件内部自动完成 @Inject 字段赋值 无需手动调用 DaggerComponent

4. 常用注解对比表

为了方便查阅,我把几个常用注解的职责列一下:

注解 作用目标 核心功能
@HiltAndroidApp Application 类 启动 Hilt,生成顶层组件,只能出现一次
@AndroidEntryPoint Activity, Fragment, Service, BroadcastReceiver 为组件注入依赖,生成子组件
@HiltViewModel ViewModel 类 配合 Activity/Fragment 注入 ViewModel
@Inject 构造方法或字段 告诉 Hilt 这个对象需要被注入

5. 避坑指南

  • @HiltAndroidApp 必须写在 Application 上,不能写在其他类。 我见过有人把它加在 BaseActivity 上,编译直接崩。
  • Activity 和 Fragment 的注入顺序有讲究: Fragment 在 onAttach() 之后注入,所以不要把注入逻辑写在构造方法或 onAttach() 之前。
  • 如果你用 Kotlin,@Inject 字段推荐用 lateinit var,避免空检查。Java 的话就用 @Inject 修饰,Hilt 会帮你赋值。
  • 多模块项目注意: 每个模块的 @HiltAndroidApp 只能有一个,其他模块靠 @Module 提供依赖,不要重复写 Application 注解。

核心原则: Hilt 把 Dagger 的模板代码收走了,但底层原理一样。你只要记住 —— @HiltAndroidApp 是总开关,@AndroidEntryPoint 是分开关。两个都写对,注入才能通。