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

Kotlin中Retrofit请求报IllegalStateException错误的解决求助

解决Retrofit调用API时的Expected BEGIN_OBJECT but was BEGIN_ARRAY错误

错误原因

这个异常的核心是JSON返回结构与Model类定义不匹配:

  • 你请求的API返回的是直接的啤酒对象数组(格式为[{}, {}, ...])
  • 但你的BeerList类要求解析一个包含list字段的对象(格式为{"list": [{}, {}, ...]})
    Gson解析时发现数据开头是数组标记(BEGIN_ARRAY),但代码期望的是对象标记(BEGIN_OBJECT),因此抛出该异常。该问题和DiffUtil无关,因为错误发生在数据解析阶段,还未到列表渲染环节。

解决方案

1. 简化Model类

删除外层的BeerList包装类,直接使用单个啤酒数据类(可重命名为Beer提升可读性):

package com.example.beercatalog.model

data class Beer(
    val alcohol: String,
    val blg: String,
    val brand: String,
    val hop: String,
    val ibu: String,
    val id: Int,
    val malts: String,
    val name: String,
    val style: String,
    val uid: String,
    val yeast: String
)

2. 修改Retrofit接口

确保API方法返回的是Call<List<Beer>>类型,而非Call<BeerList>:

interface BeerAPI {
    @GET
    fun getBeers(@Url url: String): Call<List<Beer>>
}

3. 更新MainActivity中的请求逻辑

调整回调类型为Callback<List<Beer>>,直接用返回的列表初始化Adapter(注意空安全处理):

BeerRetrofit().getInstance()!!
    .beerAPI
    .getBeers(url)
    .enqueue(object : Callback<List<Beer>>{
        override fun onResponse(call: Call<List<Beer>>, response: Response<List<Beer>>) {
            val beers = response.body() ?: emptyList()
            adapter = BeeraAdapter(beers)
            binding.recyclerView.adapter = adapter
        }

        override fun onFailure(call: Call<List<Beer>>, t: Throwable) {
            Toast.makeText(applicationContext, t.localizedMessage, Toast.LENGTH_SHORT)
                .show()
        }
    })

4. 适配Adapter类

修改Adapter的构造参数类型为List<Beer>,并调整内部数据引用:

package com.example.beercatalog.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.beercatalog.databinding.ListItemBinding
import com.example.beercatalog.model.Beer

class BeeraAdapter(private val listItem : List<Beer>) : RecyclerView.Adapter<BeeraAdapter.ViewHolderBeer>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderBeer {
        val binding = ListItemBinding.inflate(LayoutInflater.from(parent.context),parent ,false)
        return ViewHolderBeer(binding)
    }

    override fun getItemCount(): Int {
      return listItem.size
    }

    override fun onBindViewHolder(holder: ViewHolderBeer, position: Int) {
        val beer = listItem[position]
        holder.binding.beerName.text = beer.name
        holder.binding.beerBrandName.text = beer.brand
        holder.binding.alcoholperc.text = beer.alcohol
    }

    class ViewHolderBeer(var binding : ListItemBinding) : RecyclerView.ViewHolder(binding.root){

    }
}

验证建议

可以直接在浏览器中访问你的API地址https://random-data-api.com/api/v2/beers?size=10&response_type=json,确认返回的是数组结构,调整后即可正常解析数据并展示列表。

内容的提问来源于stack exchange,提问作者Aditya Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:15:00