You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 10:19:53