如何在 Kotlin 中调用这个 API?

How to call this API in Kotlin?

我想称呼这个 API: https://dog-facts-api.herokuapp.com/api/v1/resources/dogs?number=2

如您所见,它 returns Json 包含关于狗的随机事实, 我的问题是当我将我的 baseUrl 与改造一起使用时:

private fun getRetrofit(): Retrofit{
        return Retrofit.Builder()
            .baseUrl("https://dog-facts-api.herokuapp.com/api/v1/resources/dogs?number=")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

如果我这样输入 url,它不起作用,因为它说必须以“/”结尾 但是如果我添加它,它不起作用。

另外,我试过这样写:

.baseUrl("https://dog-facts-api.herokuapp.com/api/v1/resources/")

然后这样调用:

val call = getRetrofit().create(APIService::class.java).getFactsByNumber("dogs?number=$number")

但是还是不行,报错:

E/AndroidRuntime:致命异常:DefaultDispatcher-worker-1 进程:com.eltonga.dogfacts,PID:11927 com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:预期 BEGIN_OBJECT 但在第 1 行第 2 列路径 $

BEGIN_ARRAY

我的界面:

interface APIService {
    @GET
    suspend fun getFactsByNumber(@Url url: String): Response<FactsResponse>
}

我的数据class:

data class FactsResponse(var fact: List<String>)

我调用API的函数:

private fun searchByNumber(number:Int){
        CoroutineScope(Dispatchers.IO).launch {
            val call = getRetrofit().create(APIService::class.java).getFactsByNumber("dogs?number=$number")
            val the_facts = call.body()

            runOnUiThread {
                if(call.isSuccessful){
                    val factsData = the_facts?.fact ?: emptyList()
                    facts.clear()
                    facts.addAll(factsData)
                    adapter.notifyDataSetChanged()
                }else{
                    Toast.makeText(binding.btnGo.context, "Error", Toast.LENGTH_SHORT).show()
                }
            }

        }
    }

我能做什么?我是 API

的新手

Expected BEGIN_OBJECT but was BEGIN_ARRAY

以上错误表明 API 响应在根 处有一个 array/list 并且您正在尝试将响应反序列化为 不是 array/list.

的对象
interface APIService {
    @GET
    suspend fun getFactsByNumber(@Url url: String): Response<FactsResponse>
}

data class FactsResponse(var fact: List<String>)

如果响应采用以下格式,这将有效

{
  "fact": [
    "Greyhounds can reach a speed of up to 45 miles per hour.",
    "The average dog can run about 19 mph. Greyhounds are the fastest dogs on Earth and can run at speeds of 45 mph."
  ]
}

但由于响应采用以下格式

[
  {
    "fact": "Greyhounds can reach a speed of up to 45 miles per hour."
  },
  {
    "fact": "The average dog can run about 19 mph. Greyhounds are the fastest dogs on Earth and can run at speeds of 45 mph."
  }
]

您需要用 List 包裹 return 类型,而 class 应该只有一个 fact 字符串字段。所以函数和数据class应该定义为

interface APIService {
    @GET
    suspend fun getFactsByNumber(@Url url: String): Response<List<FactsResponse>>
}

data class FactsResponse(val fact: String)

此外,定义接口函数以避免每次都传递它 "dogs?number=$number" 的更好方法是

interface APIService {
    @GET("dogs")
    suspend fun getFactsByNumber(@Query("number") number: String): Response<List<FactsResponse>>
}

并将函数调用为

val apiService = getRetrofit().create(APIService::class.java)

val call = apiService.getFactsByNumber(number) // where number is already defined and initialized with a value