Kotlin结合协程使用Retrofit2调用PokeApi返回空值解决方案求助
问题核心原因
- Retrofit 搭配 Gson 转换器无法直接将接口返回的 JSON 数据解析为
LiveData类型,你在 API 接口、远程数据源返回值中额外套的LiveData层会导致 Gson 解析失败,最终返回的实体所有属性为空。 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
相关产品推荐
相关产品推荐

