Android Kotlin中使用Dagger或Hilt实现依赖注入以完成API数据请求的完整示例与最佳实践
Android Kotlin中使用Dagger或Hilt实现依赖注入以完成API数据请求的完整示例与最佳实践
嗨,我来帮你梳理一下用Hilt(Google官方推荐的Dagger简化版)实现DI并配合Retrofit请求API的完整流程——它比直接用Dagger简单太多,还自动适配Android组件生命周期,非常适合你的场景。
为什么选Hilt而不是Dagger?
Hilt是基于Dagger的Android专用DI框架,它帮我们省去了Dagger中大量手动绑定组件的模板代码,还内置了Android组件(Activity、Fragment、ViewModel等)的生命周期绑定逻辑,Google官方维护,稳定性和兼容性都更有保障。
步骤1:配置Hilt与Retrofit依赖
先把需要的依赖加到项目里:
项目级build.gradle.kts(Groovy版本类似)
plugins { id("com.android.application") version "7.4.2" apply false id("org.jetbrains.kotlin.android") version "1.8.20" apply false id("com.google.dagger.hilt.android") version "2.44" apply false }
模块级build.gradle.kts
plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("com.google.dagger.hilt.android") id("kotlin-kapt") // 用于Hilt注解编译 } android { compileSdk 33 defaultConfig { applicationId "com.your.app.package" minSdk 21 targetSdk 33 } } dependencies { // Hilt核心依赖 implementation("com.google.dagger:hilt-android:2.44") kapt("com.google.dagger:hilt-android-compiler:2.44") // Retrofit & OkHttp implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("com.squareup.okhttp3:okhttp:4.10.0") implementation("com.squareup.okhttp3:logging-interceptor:4.10.0") // 调试用日志拦截器 // ViewModel & LiveData implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1") implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1") implementation("androidx.activity:activity-ktx:1.7.2") } kapt { correctErrorTypes = true }
步骤2:初始化Hilt入口
创建自定义Application类,用@HiltAndroidApp标记——这是Hilt的全局入口点:
@HiltAndroidApp class MyApp : Application()
然后在AndroidManifest.xml中注册这个Application:
<application android:name=".MyApp" <!-- 其他配置 --> > <!-- 你的Activity声明 --> </application>
步骤3:创建Retrofit相关的Hilt模块
用@Module和@InstallIn注解定义全局依赖的提供逻辑,比如Retrofit、OkHttp和API服务:
@Module @InstallIn(SingletonComponent::class) // 标记为全局单例 object NetworkModule { // 提供OkHttpClient实例,添加日志拦截器方便调试 @Provides @Singleton fun provideOkHttpClient(): OkHttpClient { val loggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } return OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .build() } // 提供Retrofit实例 @Provides @Singleton fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit { return Retrofit.Builder() .baseUrl("https://your-api-base-url.com/") // 替换成你的API地址 .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build() } // 提供API Service接口实例 @Provides @Singleton fun provideApiService(retrofit: Retrofit): ApiService { return retrofit.create(ApiService::class.java) } } // 定义你的API接口 interface ApiService { @GET("users") suspend fun getUsers(): List<User> } // 数据模型类 data class User(val id: Int, val name: String, val email: String)
步骤4:创建Repository并注入API服务
Repository负责封装数据层逻辑(API请求、本地缓存等),用@Inject让Hilt自动注入依赖:
// 推荐用接口定义Repository,方便后续替换实现(比如测试用Mock) interface UserRepository { suspend fun getUsers(): Result<List<User>> } // 具体实现类 class UserRepositoryImpl @Inject constructor( private val apiService: ApiService ) : UserRepository { override suspend fun getUsers(): Result<List<User>> { return try { val users = apiService.getUsers() Result.success(users) } catch (e: Exception) { Result.failure(e) } } } // 绑定Repository接口与实现类的Module @Module @InstallIn(SingletonComponent::class) abstract class RepositoryModule { @Binds @Singleton abstract fun bindUserRepository(impl: UserRepositoryImpl): UserRepository }
用@Binds比@Provides更高效,它是编译时绑定,不需要手动写实例化逻辑。
步骤5:创建ViewModel并注入Repository
用@HiltViewModel标记ViewModel,构造函数注入Repository,然后处理数据请求:
@HiltViewModel class UserViewModel @Inject constructor( private val userRepository: UserRepository ) : ViewModel() { private val _users = MutableLiveData<Result<List<User>>>() val users: LiveData<Result<List<User>>> = _users // 触发数据请求 fun fetchUsers() { viewModelScope.launch { // 自动跟随ViewModel生命周期的协程作用域 _users.value = userRepository.getUsers() } } }
步骤6:在Activity/Fragment中使用ViewModel
在Activity/Fragment上添加@AndroidEntryPoint注解,然后用by viewModels()获取ViewModel实例:
@AndroidEntryPoint class MainActivity : AppCompatActivity() { private val viewModel: UserViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 观察数据变化,更新UI viewModel.users.observe(this) { result -> when (result) { is Result.Success -> { // 显示用户列表 val userList = result.data // 比如更新RecyclerView } is Result.Failure -> { // 处理错误,比如显示Toast val errorMsg = result.exception.message ?: "请求失败" Toast.makeText(this, errorMsg, Toast.LENGTH_SHORT).show() } } } // 触发请求 viewModel.fetchUsers() } }
最佳实践总结
- 优先用Hilt:比Dagger节省大量模板代码,适配Android生命周期,官方支持更稳定。
- 依赖倒置原则:用接口定义Repository,注入具体实现,方便后续替换为Mock实现(比如单元测试)。
- 合理管理Scope:用
@Singleton(全局单例)、@ActivityScoped(Activity生命周期)、@ViewModelScoped(ViewModel生命周期)等注解控制依赖的生命周期,避免内存泄漏。 - 单一职责:Repository只处理数据逻辑,ViewModel只处理UI状态,Activity/Fragment只负责渲染UI和处理用户交互。
- 不要直接注入Retrofit到ViewModel:通过Repository封装API请求,降低耦合,方便后续添加缓存或切换数据源。
- 用Result封装状态:统一处理成功/失败/加载状态,让UI层逻辑更清晰。
备注:内容来源于stack exchange,提问作者Lily Monta
相关产品推荐
相关产品推荐

