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

