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

Kotlin结合协程使用Retrofit2调用PokeApi返回空值解决方案求助

问题核心原因
  1. Retrofit 搭配 Gson 转换器无法直接将接口返回的 JSON 数据解析为 LiveData 类型,你在 API 接口、远程数据源返回值中额外套的 LiveData 层会导致 Gson 解析失败,最终返回的实体所有属性为空。
  2. viewPokemonEvolution 方法中通过 CoroutineScope.launch 启动的协程是异步执行的,方法返回时协程还未完成网络请求,remotePokemonEvolutionFormData 还未被赋值,强制用 !! 拆包还会大概率触发空指针崩溃。
修复步骤

1. 移除所有接口返回值中多余的 LiveData 包装

修改 PokemonApi 接口

interface PokemonApi {
    @GET("pokemon-form/{id}")
    suspend fun getPokemonInfo(@Path("id") idPokemon: Long): Response<PokemonFormResponse>

    @GET("pokemon/{name}")
    suspend fun getPokemonExtendedInfo(@Path("name") pokemonName: String): Response<PokemonExtendedInfoResponse>
}

修改 IRemoteDataSource 接口

interface IRemoteDataSource {
    suspend fun downloadPokemonViewedData(id: Long): Response<PokemonFormResponse>
    suspend fun downloadPokemonCatchedData(name: String): Response<PokemonExtendedInfoResponse>
}

修改 RemoteDataSource 实现

Retrofit 的 suspend 方法本身是主安全的,不需要手动切换调度器:

override suspend fun downloadPokemonViewedData(id: Long): Response<PokemonFormResponse> {
    return apiServices.getPokemonInfo(id)
}

override suspend fun downloadPokemonCatchedData(name: String): Response<PokemonExtendedInfoResponse> {
    return apiServices.getPokemonExtendedInfo(name)
}

2. 修正 DataProvider 中协程的使用逻辑

这里推荐两种实现方案,二选一即可:

方案一:使用官方 LiveData 协程构建器(推荐)

需要先引入 lifecycle-livedata-ktx 依赖:

implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"

修改 viewPokemonEvolution 方法:

fun viewPokemonEvolution(id: Long): LiveData<PokemonFormResponse?> = liveData(Dispatchers.IO) {
    val response = remoteDataSource.downloadPokemonViewedData(id)
    emit(if (response.isSuccessful) response.body() else null)
}

方案二:手动创建 MutableLiveData 赋值

fun viewPokemonEvolution(id: Long): LiveData<PokemonFormResponse?> {
    val result = MutableLiveData<PokemonFormResponse?>()
    CoroutineScope(Dispatchers.IO).launch {
        val response = remoteDataSource.downloadPokemonViewedData(id)
        result.postValue(if (response.isSuccessful) response.body() else null)
    }
    return result
}
注意事项
  • 不要使用 !! 强制拆包可空变量,避免不必要的空指针崩溃
  • 协程调度器优先使用 Dispatchers.IO 处理网络、数据库等IO操作

内容的提问来源于stack exchange,提问作者Manuel Lucas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:15:02