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

Retrofit API调用时Flow代码块未执行的问题求助

问题分析与解决方案

核心问题点

  1. toResultFlow未执行API调用:你定义的toResultFlow仅发射了Result.Loading,完全没调用传入的call参数,导致apiService.getAppConfig()从未执行。
  2. Repository的Flow未转发数据:AppConfigRepositoryImp的flow块仅调用了remoteDataSource.getAppConfigData(),但未将该Flow的结果发射出去,等同于空Flow。
  3. ViewModel未订阅Flow:ViewModel中获取Flow后未调用collect等操作符订阅,即便Flow有数据也无法更新UI状态。

修正后的代码

1. 修复AppConfigRemoteDataSourceImpl的toResultFlow函数

在Flow中执行API调用,并根据响应发射对应状态:

class AppConfigRemoteDataSourceImpl @Inject constructor(
    private val apiService: ApiService
) : AppConfigRemoteDataSource {
    override suspend fun getAppConfigData(): Flow<Result<AppConfig>?> = toResultFlow {
        apiService.getAppConfig()
    }

    private fun <T> toResultFlow(call: suspend () -> Response<T>?): Flow<Result<T>?> {
        return flow {
            emit(Result.Loading)
            try {
                val response = call() // 执行API调用
                response?.let {
                    if (it.isSuccessful) {
                        emit(Result.Success(it.body()))
                    } else {
                        emit(Result.Error(Throwable("HTTP错误: ${it.code()}")))
                    }
                } ?: emit(Result.Error(Throwable("API返回空响应")))
            } catch (e: Exception) {
                emit(Result.Error(e))
            }
        }
    }
}

2. 修复AppConfigRepositoryImp的getAppConfig方法

直接返回RemoteDataSource的Flow即可,无需额外包裹:

@Singleton
class AppConfigRepositoryImp @Inject constructor(
    private val remoteDataSource: AppConfigRemoteDataSource
) : AppConfigRepository {
    override suspend fun getAppConfig(): Flow<Result<AppConfig>?> = 
        remoteDataSource.getAppConfigData()
}

3. 修复ViewModel的getAppConfig方法

收集Flow结果并更新UI状态:

private fun getAppConfig() = viewModelScope.launch {
    _appConfigFlow.update {
        AppConfigState.Loading
    }
    // 订阅Flow,处理结果
    getAppConfigUseCase.invoke().collect { result ->
        _appConfigFlow.update {
            when (result) {
                is Result.Loading -> AppConfigState.Loading
                is Result.Success -> AppConfigState.Success(result.data)
                is Result.Error -> AppConfigState.Error(result.exception)
                else -> AppConfigState.Error(Throwable("未知结果类型"))
            }
        }
    }
}

4. 补充Result密封类定义

确保状态类型完整:

sealed class Result<out T> {
    object Loading : Result<Nothing>()
    data class Success<out T>(val data: T?) : Result<T>()
    data class Error(val exception: Throwable) : Result<Nothing>()
}

内容的提问来源于stack exchange,提问作者Rahul Surendran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 08:07:25