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
相关产品推荐
相关产品推荐

