2. Application类注解与Hilt入口设置:@HiltAndroidApp

@HiltAndroidApp 是 Hilt 依赖注入框架在 Android 应用中的唯一根入口。该注解必须标注在自定义的 Application 类上,用于触发 Hilt 的代码生成器,在编译期自动生成基础组件容器(SingletonComponent)及其子组件。没有 @HiltAndroidApp,Hilt 无法扫描其他注解、无法生成依赖图、整个注入链路会直接断裂。

Hilt 核心注解标注位置作用与初始化时机
@HiltAndroidAppApplication 类生成根组件 SingletonComponent,在 Application.onCreate 之前完成组件容器初始化
@AndroidEntryPointActivity / Fragment / View / Service生成子组件(ActivityComponent 等)并注入依赖
@HiltViewModelViewModel 类配合 Navigation 或 @AndroidEntryPoint 使用,提供 ViewModel 注入
@Module普通类作为组件依赖提供者,需配合 @InstallIn 指定安装到的组件

2.1 @HiltAndroidApp 流程原理

编译时 Hilt Gradle Plugin 会扫描 @HiltAndroidApp 标注的 Application 类,自动生成以 Hilt_ 为前缀的父类(如 Hilt_MyApplication)。该父类在 onCreate() 之前执行以下工作:

  1. 初始化 SingletonComponent —— 整个应用的根组件容器。
  2. 创建组件依赖图,将 @Module 中提供的依赖注册到图中。
  3. 为后续所有 @AndroidEntryPoint 的子组件提供父组件依赖。
  4. 设置 Application 级别的 ComponentManager(全局单例持有者)。
关键点: Hilt 在编译期完成组件生成,运行时组件容器在 Application 的 attachBaseContext() 与 onCreate() 之间完成初始化,不会阻塞主线程 UI 渲染。

2.2 @HiltAndroidApp 组件容器初始化流程

@HiltAndroidApp 触发组件容器初始化流程 Application 类 @HiltAndroidApp Hilt Gradle Plugin SingletonComponent ActivityComponent FragmentComponent ViewComponent 所有子组件的依赖都来自 SingletonComponent 的提供

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"
}
最佳实践: Hilt 要求 @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 expectedApplication 类没有标注 @HiltAndroidApp在 Application 类上添加 @HiltAndroidApp
运行时 ClassNotFoundExceptionAndroidManifest 中未声明 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 在编译期就会报错,不会留到运行时才发现。