网络请求方案记录:Kimi AI提供的方案-使用 Kotlin 协程 + Flow + Retrofit + OkHttp进行请求

985 阅读1分钟

下面给出一份 2024-07 最新、可直接落地的「网络请求框架」模板,全部基于 Kotlin 协程 + Flow + Retrofit + OkHttp,并遵循 MVVM + Repository 架构。你只需复制粘贴即可跑通业务。


1. 工程依赖(build.gradle.kts

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.0")

    implementation("com.squareup.retrofit2:retrofit:2.11.0")
    implementation("com.squareup.retrofit2:converter-gson:2.11.0")
    implementation("com.squareup.okhttp3:okhttp:4.12.0")
    implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
}

2. 数据层:Retrofit 接口 & 响应封装

// 1) 通用响应包装
sealed class ApiResult<out T> {
    data class Success<out T>(val data: T) : ApiResult<T>()
    data class Error(val exception: Throwable) : ApiResult<Nothing>()
}

// 2) 业务实体
data class User(val id: Int, val name: String)

// 3) Retrofit 接口
interface ApiService {
    @GET("user/{id}")
    suspend fun getUser(@Path("id") id: Int): User
}

3. 网络引擎单例

object NetworkModule {

    private val okHttp = OkHttpClient.Builder()
        .connectTimeout(15, TimeUnit.SECONDS)
        .readTimeout(15, TimeUnit.SECONDS)
        .addInterceptor(HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        })
        .build()

    val api: ApiService = Retrofit.Builder()
        .baseUrl("https://api.example.com/")
        .client(okHttp)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(ApiService::class.java)
}

4. Repository:把 挂起函数 封装成 Flow

class UserRepository(
    private val api: ApiService = NetworkModule.api
) {
    fun userFlow(id: Int): Flow<ApiResult<User>> = flow {
        emit(ApiResult.Success(api.getUser(id)))   // 网络请求
    }
        .flowOn(Dispatchers.IO)                    // 切换到 IO
        .catch { e -> emit(ApiResult.Error(e)) }   // 统一异常兜底
}

关键点:flow {} 保证冷流特性;flowOn(Dispatchers.IO) 只影响上游;catch 捕获下游异常。


5. ViewModel:UI 状态 = StateFlow

class UserViewModel(
    private val repo: UserRepository = UserRepository()
) : ViewModel() {

    private val _uiState = MutableStateFlow<ApiResult<User>?>(null)
    val uiState: StateFlow<ApiResult<User>?> = _uiState

    fun load(id: Int) {
        repo.userFlow(id)
            .onStart { _uiState.value = null }        // 空状态/加载中
            .onEach { _uiState.value = it }           // 业务结果
            .launchIn(viewModelScope)                 // 自动跟随生命周期
    }
}

6. UI 层(以 Compose 为例)

@Composable
fun UserScreen(vm: UserViewModel = viewModel()) {
    val state by vm.uiState.collectAsStateWithLifecycle()

    when (val s = state) {
        null -> CircularProgressIndicator()
        is ApiResult.Success -> Text("Hi, ${s.data.name}!")
        is ApiResult.Error   -> Text("Error: ${s.exception.message}")
    }

    LaunchedEffect(Unit) { vm.load(1) }
}

若使用 View 体系,可替换成 repeatOnLifecycle(Lifecycle.State.STARTED) 收集。


7. 进阶扩展(可选)

需求方案
并发多个接口zip / combine
分页Pager<Int, User> + Paging 3
缓存优先flow { emit(cache) } .combine(networkFlow)
超时/重试.timeout(5.seconds) / .retry(3)

8. 官方完整教程 & 源码