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

使用Retrofit调用PokeAPI返回Null但Postman正常的问题排查

问题描述

尝试用Retrofit对接PokeAPI,调用pokemon-species接口时返回Null,但该接口在Postman中请求正常。相关代码如下:

Retrofit客户端代码

object RetrofitClient {

    private const val BASE_URL = "https://pokeapi.co/api/v2/"

    private val retrofit: Retrofit by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    fun <T> createService(serviceClass: Class<T>): T {
        return retrofit.create(serviceClass)
    }
}

API接口定义

interface PokeApiService {

    @GET("pokemon/{id}")
    fun getPokemon(@Path("id") pokemonId: Int): Response<Pokemon>

    @GET("pokemon-species")
    fun getMaxPokemonCount(): Response<PokemonSpeciesResponse>
}

数据类定义

data class Pokemon(
    val name: String,
    val types: List<PokemonType>
)

data class PokemonType(
    val slot: Int,
    val type: Type
)

data class Type(
    val name: String
)

data class PokemonSpeciesResponse(
    val count: Int
)

返回Null的调用代码

private fun getMaxPokemonCount(): Int? {
        val response = pokeApiService.getMaxPokemonCount()
    try {
        if (response.isSuccessful) {
            Log.d("Test", "Response: $response")
            val count = response.body()?.count
            return count
        }

    } catch (e: Exception) {
        Log.d("Test", "Status code: ${response.code()}")
    }
    return null
}

Postman返回示例

{
    "count": 1017,
    "next": "https://pokeapi.co/api/v2/pokemon-species?offset=20&limit=20",
    "previous": null,
    "results": [
        {
            "name": "bulbasaur",
            "url": "https://pokeapi.co/api/v2/pokemon-species/1/"
        },
        {
            "name": "ivysaur",
            "url": "https://pokeapi.co/api/v2/pokemon-species/2/"
        },
        ...
    ]
}
问题分析与解决办法

核心问题

  1. 主线程执行网络请求:Android禁止在主线程发起同步网络请求,直接调用pokeApiService.getMaxPokemonCount()会触发NetworkOnMainThreadException,且该异常发生在try块之外,无法被捕获,导致方法直接跳转到最后返回null。
  2. 异常捕获范围错误:网络请求调用语句不在try块内,即使发生异常也无法被捕获处理。

修正方案

方案1:使用Kotlin协程实现异步请求(推荐)

1. 修改API接口,添加suspend关键字

interface PokeApiService {

    @GET("pokemon/{id}")
    suspend fun getPokemon(@Path("id") pokemonId: Int): Response<Pokemon>

    @GET("pokemon-species")
    suspend fun getMaxPokemonCount(): Response<PokemonSpeciesResponse>
}

2. 改为挂起函数调用(在协程作用域内执行)

private suspend fun getMaxPokemonCount(): Int? {
    return try {
        val response = pokeApiService.getMaxPokemonCount()
        if (response.isSuccessful) {
            Log.d("Test", "Response: $response")
            response.body()?.count
        } else {
            Log.d("Test", "Status code: ${response.code()}")
            null
        }
    } catch (e: Exception) {
        Log.d("Test", "Error: ${e.message}")
        null
    }
}

调用示例(在Activity/Fragment的生命周期协程中):

lifecycleScope.launch {
    val maxCount = getMaxPokemonCount()
    // 处理拿到的宝可梦总数
}

方案2:使用Retrofit异步回调

1. 修改API接口方法返回Call类型

interface PokeApiService {

    @GET("pokemon/{id}")
    fun getPokemon(@Path("id") pokemonId: Int): Call<Pokemon>

    @GET("pokemon-species")
    fun getMaxPokemonCount(): Call<PokemonSpeciesResponse>
}

2. 用enqueue发起异步请求

private fun getMaxPokemonCount() {
    pokeApiService.getMaxPokemonCount().enqueue(object : Callback<PokemonSpeciesResponse> {
        override fun onResponse(call: Call<PokemonSpeciesResponse>, response: Response<PokemonSpeciesResponse>) {
            if (response.isSuccessful) {
                val count = response.body()?.count
                Log.d("Test", "Count: $count")
                // 处理拿到的总数
            } else {
                Log.d("Test", "Status code: ${response.code()}")
            }
        }

        override fun onFailure(call: Call<PokemonSpeciesResponse>, t: Throwable) {
            Log.d("Test", "Error: ${t.message}")
        }
    })
}

额外验证

数据类PokemonSpeciesResponse定义正确,Gson会自动忽略JSON中多余的字段(如next、previous、results),无需修改。

内容的提问来源于stack exchange,提问作者Kalaitos Ornitier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 17:40:31