一、依赖注入(DI)与框架概述
依赖注入 是一种设计模式,通过将对象的创建和依赖关系从代码中解耦,提升代码的可测试性、可维护性和可扩展性。在 Android 开发中,Dagger 和 Hilt 是主流的 DI 框架:
- Dagger:基于 Java 注解处理器(APT)的编译时 DI 框架,生成高效代码,但配置复杂。
- Hilt:基于 Dagger 的 Android 专用框架,简化配置并与 Android 组件深度集成。
二、Dagger/Hilt 实现原理
1、Dagger 核心原理
- 注解处理器 :在编译时解析
@Component
、@Module
等注解,生成DaggerXxxComponent
类。 - 组件(Component):作为依赖注入的容器,连接模块(Module)和注入目标。
- 依赖图:构建对象依赖关系图,确保依赖按需创建并正确传递。
2、Hilt 的优化
- 预定义组件 :自动为
Activity
、Fragment
、ViewModel
等生成组件,无需手动声明。 - 内置绑定 :通过
@AndroidEntryPoint
注解自动注入 Android 框架类(如Application
)。 - 简化作用域 :通过
@Singleton
、@ActivityScoped
等注解管理生命周期。
三、Hilt 使用示例
1、项目配置(Gradle)
gradle
// 根 build.gradle
dependencies {
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.48'
}
// app/build.gradle
plugins {
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
dependencies {
implementation 'com.google.dagger:hilt-android:2.48'
kapt 'com.google.dagger:hilt-android-compiler:2.48'
// 可选:Hilt 和 ViewModel 集成
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
kapt 'androidx.hilt:hilt-compiler:1.0.0'
}
2、初始化 Hilt
kotlin
// Application 类
@HiltAndroidApp
class MyApp : Application()
3、定义依赖模块
kotlin
@Module
@InstallIn(SingletonComponent::class) // 模块作用域为全局单例
object AppModule {
@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
fun provideApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
}
4、注入依赖到 Activity
kotlin
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var apiService: ApiService // 自动注入
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 直接使用 apiService
apiService.fetchData()
}
}
5、ViewModel 注入
kotlin
@HiltViewModel
class UserViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() {
fun loadUser() = userRepository.getUser()
}
四、使用场景与优势
1、适用场景
- 复杂依赖管理 :多层依赖(如
ViewModel
→Repository
→DataSource
)。 - 全局单例:网络客户端(Retrofit)、数据库(Room)、SharedPreferences。
- 测试替代:通过替换 Module 提供 Mock 对象进行单元测试。
- 多环境配置:根据 Build 类型切换 API 地址或数据源。
2、Hilt 的核心优势
- 简化配置:自动生成组件,减少模板代码。
- 生命周期感知:自动处理 Android 组件的生命周期绑定。
- 与 Jetpack 集成:支持 ViewModel、WorkManager 等组件。
五、Dagger vs Hilt 对比
特性 | Dagger | Hilt |
---|---|---|
配置复杂度 | 高(需手动定义组件和子组件) | 低(预定义组件,自动注入) |
Android 集成 | 需要自行绑定生命周期 | 深度集成,支持 @AndroidEntryPoint |
代码生成 | 显式生成 DaggerComponent |
隐式生成,更简洁 |
适用项目 | 超大型项目,需要高度自定义 | 中小型项目,快速开发 |
六、常见问题与解决
1、编译错误:找不到绑定
- 原因:未提供依赖或 Module 未正确安装。
- 解决 :检查
@Provides
方法或添加@Inject
构造函数。
2、作用域冲突
- 现象:同一作用域内多次创建实例。
- 解决 :使用
@Singleton
或自定义作用域注解。
3、循环依赖
- 示例:A 依赖 B,B 又依赖 A。
- 解决 :重构代码,或使用
@Lazy
延迟注入。
七、总结
-
Hilt 是 Android DI 的未来:Google 官方推荐,适合大多数项目。
-
最佳实践:
- 使用
@HiltViewModel
注入 ViewModel。 - 通过
@InstallIn
控制模块作用域。 - 优先使用构造函数注入(
@Inject constructor
)。
- 使用
-
性能优化:合理使用作用域,避免全局单例滥用。