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

Android Studio中使用RecyclerView结合API与GSON无法加载全部数据,仅显示单个条目

Android Studio中使用RecyclerView结合API与GSON无法加载全部数据,仅显示单个条目

嗨,我仔细看了你的代码,问题其实出在数据层级的理解和Adapter的适配逻辑上,咱们一步步拆解解决:

问题核心分析

你现在把整个API响应对象AllResponseTrending当成了RecyclerView的列表项,但实际上这个对象只是一个"数据容器",真正要展示的列表数据是它内部的results字段(也就是List<ResultsItem>)。这就导致RecyclerView只拿到了1个条目(整个容器对象),然后你在ViewHolder里又把所有结果都塞到这一个条目里,自然就只显示一行,还堆了所有内容。

具体修改步骤

1. 重构MovieAdapter,适配单个结果条目

把Adapter的处理对象从AllResponseTrending改成ResultsItem,因为每个列表项对应一个独立的影视条目:

class MovieAdapter(
    private val onItemClick: OnClickListener
) : RecyclerView.Adapter<MovieAdapter.ViewHolder>() {

    // 改成针对单个ResultsItem的DiffUtil判断逻辑
    private val diffCallBack = object : DiffUtil.ItemCallback<ResultsItem>() {
        override fun areContentsTheSame(oldItem: ResultsItem, newItem: ResultsItem): Boolean {
            // 比较条目内容是否一致,可根据需求扩展字段
            return oldItem.name == newItem.name && oldItem.overview == newItem.overview
        }

        override fun areItemsTheSame(oldItem: ResultsItem, newItem: ResultsItem): Boolean {
            // 用唯一id判断是否为同一条目,保证DiffUtil正确性
            return oldItem.id == newItem.id
        }
    }

    fun submitData(value: List<ResultsItem>?) = differ.submitList(value)

    private val differ = AsyncListDiffer(this, diffCallBack)

    inner class ViewHolder(private val binding: ItemRowBinding)
        : RecyclerView.ViewHolder(binding.root) {
        fun bind(data: ResultsItem) {
            binding.apply {
                // 直接用单个ResultsItem的字段,不用遍历整个列表!
                // 兼容电影的title和剧集的name字段
                tvJudul.text = data.name ?: data.title
                tvDeskripsi.text = data.overview
                root.setOnClickListener {
                    onItemClick.onClickItem(data)
                }
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        return ViewHolder(ItemRowBinding.inflate(inflater, parent, false))
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val data = differ.currentList[position]
        holder.bind(data)
    }

    override fun getItemCount(): Int = differ.currentList.size

    interface OnClickListener {
        fun onClickItem(data: ResultsItem)
    }
}

2. 修改HomeFragment的数据提交逻辑

在showList方法里,要把AllResponseTrending中的results列表提交给Adapter,而不是把整个容器对象包装成列表:

private fun showList(data: AllResponseTrending?) {
    // 复用已初始化的Adapter,避免重复创建浪费资源
    val adapter = binding.rvHomepage.adapter as MovieAdapter
    data?.results?.let {
        adapter.submitData(it)
    }
}

同时,更新onClickItem的参数类型,适配新的Adapter回调:

override fun onClickItem(data: ResultsItem) {
    val bundle = Bundle()
    // 可以按需传递条目数据到详情页,比如id、标题等
    bundle.putInt("item_id", data.id)
    bundle.putString("item_title", data.name ?: data.title)
    view?.findNavController()?.navigate(R.id.action_homeFragment_to_detailFragment, bundle)
}

3. 保留原有初始化逻辑(无需改动)

onViewCreated里的Adapter初始化逻辑是正确的,保持原样即可:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    // ... 其他UI点击逻辑省略 ...

    binding.rvHomepage.apply {
        layoutManager = LinearLayoutManager(activity)
        adapter = MovieAdapter(this@HomeFragment)
    }

    fetchAllData()
}

补充说明

你的GSON模型类AllResponseTrending和ResultsItem是正确的,和API返回的JSON结构完全匹配,不用修改。只是要注意返回结果里,电影用title字段,剧集用name字段,所以在Adapter的bind方法里做了兼容处理,确保两种类型的条目都能正确显示标题。

这样修改后,RecyclerView就能正确加载所有的影视条目,每个条目对应一个独立的结果啦!

备注:内容来源于stack exchange,提问作者PACE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 08:58:11