2. Application类注解与Hilt入口设置:@HiltAndroidApp
@HiltAndroidApp 是 Hilt 依赖注入框架在 Android 应用中的唯一根入口。该注解必须标注在自定义的 Application 类上,用于触发 Hilt 的代码生成器,在编译期自动生成基础组件容器(SingletonComponent)及其子组件。没有 @HiltAndroidApp,Hilt 无法扫描其他注解、无法生成依赖图、整个注入链路会直接断裂。
| Hilt 核心注解 | 标注位置 | 作用与初始化时机 |
|---|---|---|
@HiltAndroidApp | Application 类 | 生成根组件 SingletonComponent,在 Application.onCreate 之前完成组件容器初始化 |
@AndroidEntryPoint | Activity / Fragment / View / Service | 生成子组件(ActivityComponent 等)并注入依赖 |
@HiltViewModel | ViewModel 类 | 配合 Navigation 或 @AndroidEntryPoint 使用,提供 ViewModel 注入 |
@Module | 普通类 | 作为组件依赖提供者,需配合 @InstallIn 指定安装到的组件 |
2.1 @HiltAndroidApp 流程原理
编译时 Hilt Gradle Plugin 会扫描 @HiltAndroidApp 标注的 Application 类,自动生成以 Hilt_ 为前缀的父类(如 Hilt_MyApplication)。该父类在 onCreate() 之前执行以下工作:
- 初始化 SingletonComponent —— 整个应用的根组件容器。
- 创建组件依赖图,将
@Module中提供的依赖注册到图中。 - 为后续所有
@AndroidEntryPoint的子组件提供父组件依赖。 - 设置 Application 级别的
ComponentManager(全局单例持有者)。
attachBaseContext() 与 onCreate() 之间完成初始化,不会阻塞主线程 UI 渲染。
2.2 @HiltAndroidApp 组件容器初始化流程
2.3 具体实现步骤
步骤一:创建 Application 子类并添加 @HiltAndroidApp
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Hilt 组件容器在 super.onCreate 之前已经完成初始化
}
}
步骤二:在 AndroidManifest.xml 中声明自定义 Application
<application
android:name=".MyApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
... >
<activity ... />
</application>
步骤三:确保 build.gradle(Module: app)中配置 Hilt 依赖
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'dagger.hilt.android.plugin'
}
android { ... }
dependencies {
implementation "com.google.dagger:hilt-android:2.48"
kapt "com.google.dagger:hilt-compiler:2.48"
}
@HiltAndroidApp 的 Application 类必须是 public(Java)或包含在标准模块中。组件容器只会初始化一次,无需手动调用任何初始化方法。
2.4 全局组件容器的层次结构
@HiltAndroidApp 生成的 SingletonComponent 是组件树的根,其生命周期与 Application 完全一致。所有 @InstallIn(SingletonComponent.class) 的 Module 都会把依赖注册到根容器中。子组件(如 ActivityComponent)从根容器获取父依赖,同时可以拥有自己的 Scope 和生命周期。
- SingletonComponent —— 仅存在一个实例,提供全局单例依赖。
- ActivityComponent —— 每个 Activity 一个实例,提供 Activity 级别的依赖。
- FragmentComponent —— 每个 Fragment 一个实例,依赖 ActivityComponent。
- ViewComponent —— 每个使用
@AndroidEntryPoint的自定义 View 一个实例。
2.5 调试与验证
编译项目后,在 build/generated/source/kapt/ 目录下可以找到 Hilt 自动生成的 Hilt_MyApplication 文件。如果生成成功,说明 @HiltAndroidApp 配置正确。运行时可以通过 Hilt 日志(过滤 Hilt tag)查看组件初始化详情:
// 日志输出示例(过滤 tag: Hilt)
Hilt: SingletonComponent created.
Hilt: Injecting Application class: com.example.app.MyApplication
2.6 常见错误与解决方案
| 错误现象 | 根因分析 | 修复方法 |
|---|---|---|
编译报错 @HiltAndroidApp expected | Application 类没有标注 @HiltAndroidApp | 在 Application 类上添加 @HiltAndroidApp |
| 运行时 ClassNotFoundException | AndroidManifest 中未声明 Application | 声明 android:name=".MyApplication" |
| build.gradle 中未添加插件 | Hilt Gradle Plugin 缺失 | 在 project 级 build.gradle 添加 id 'dagger.hilt.android.plugin' |
@HiltAndroidApp 和自定义的 ContentProvider 或 Instrumentation,确保 Application 的初始化顺序不会被其他组件提前打断。Hilt 只拦截 Application 的 attachBaseContext() 和 onCreate(),不会影响其他生命周期。
2.7 性能与稳定性考量
- 编译时间:
@HiltAndroidApp会触发注解处理器扫描整个模块,首次编译会增加 5~15 秒,建议开启kapt的增量编译(默认开启)来减少重复编译时间。 - 运行时开销: 组件容器初始化在 Application 的
super.onCreate()之前完成,通常耗时不到 10ms,对启动性能几乎没有影响。 - 内存占用: SingletonComponent 将持有整个应用的依赖图,一般占用数十 KB 到数百 KB,属于可接受范围。仅在极端多 Module 场景下需要注意内存消耗。
- 稳定性: 组件容器一旦初始化完成,后续所有注入操作都是安全的。如果
Module提供了错误的依赖(如循环依赖),Hilt 在编译期就会报错,不会留到运行时才发现。