如何在RecyclerView的单个item中嵌套展示ChildQuestionList子列表?
嘿,我来帮你搞定这个嵌套RecyclerView的问题!你现在遇到的核心问题是适配器没有正确处理父Item的子列表展示,而且不想重新初始化适配器对吧?下面是具体的实现步骤,都是Android开发里常用的方案:
解决方案:实现带动态子列表的嵌套RecyclerView(无需重建适配器)
1. 先把数据模型和适配器结构捋顺
首先,你的父Question模型得能容纳子列表,还要有方法动态更新子数据,这样不用动整个父列表:
public class Question { private String parentQuestion; private List<ChildQuestion> childQuestionList; // 构造器、getter方法自行补充 // 关键:给子列表加个更新方法 public void updateChildList(List<ChildQuestion> newChilds) { this.childQuestionList = newChilds; } }
然后,父RecyclerView的每个Item布局里要嵌套一个子RecyclerView,用来展示对应的ChildQuestionList。比如父Item的布局item_parent_question.xml大概是这样:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/tv_parent_question" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:textSize="18sp"/> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_child_questions" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingStart="32dp"/> </LinearLayout>
2. 改造父适配器,支持子列表动态更新
父适配器的核心是在绑定每个父Item时,给子RecyclerView设置适配器,并且提供单独更新子列表的方法,不用刷新整个父列表:
public class ParentQuestionAdapter extends RecyclerView.Adapter<ParentQuestionAdapter.ParentViewHolder> { private List<Question> mParentList; public ParentQuestionAdapter(List<Question> parentList) { this.mParentList = parentList; } // 重点:这个方法用来更新指定父Item的子列表,不用重建适配器 public void refreshChildList(int parentPos, List<ChildQuestion> newChilds) { Question targetParent = mParentList.get(parentPos); targetParent.updateChildList(newChilds); // 只通知这个位置的Item更新,比notifyDataSetChanged()高效太多 notifyItemChanged(parentPos); } @Override public void onBindViewHolder(@NonNull ParentViewHolder holder, int position) { Question currentParent = mParentList.get(position); holder.tvParent.setText(currentParent.getParentQuestion()); // 给子RecyclerView设置适配器,直接用当前父Item的子列表数据 ChildQuestionAdapter childAdapter = new ChildQuestionAdapter(currentParent.getChildQuestionList()); holder.rvChild.setAdapter(childAdapter); holder.rvChild.setLayoutManager(new LinearLayoutManager(holder.itemView.getContext())); holder.rvChild.setHasFixedSize(true); } static class ParentViewHolder extends RecyclerView.ViewHolder { TextView tvParent; RecyclerView rvChild; public ParentViewHolder(@NonNull View itemView) { super(itemView); tvParent = itemView.findViewById(R.id.tv_parent_question); rvChild = itemView.findViewById(R.id.rv_child_questions); } } }
子适配器就是普通的RecyclerView适配器,用来展示子问答:
public class ChildQuestionAdapter extends RecyclerView.Adapter<ChildQuestionAdapter.ChildViewHolder> { private List<ChildQuestion> mChildList; public ChildQuestionAdapter(List<ChildQuestion> childList) { this.mChildList = childList; } @Override public void onBindViewHolder(@NonNull ChildViewHolder holder, int position) { ChildQuestion child = mChildList.get(position); holder.tvChildQ.setText(child.getQuestion()); holder.tvChildA.setText(child.getAnswer()); } static class ChildViewHolder extends RecyclerView.ViewHolder { TextView tvChildQ; TextView tvChildA; public ChildViewHolder(@NonNull View itemView) { super(itemView); tvChildQ = itemView.findViewById(R.id.tv_child_question); tvChildA = itemView.findViewById(R.id.tv_child_answer); } } }
3. 动态更新子列表的正确操作
当你拿到某个父Item的子列表数据后(比如网络请求返回),直接调用父适配器的refreshChildList方法就行,完全不用重新创建适配器:
// 假设你拿到了第0个父Item的子列表数据 List<ChildQuestion> newChildData = ...; // 你的动态子问答数据 mParentAdapter.refreshChildList(0, newChildData);
4. 解决只显示第0个父Item的问题
你说适配器只运行一次,只展示第0个对象,大概率是这两个原因:
- 父RecyclerView没设置布局管理器!一定要加这句:
mParentRecyclerView.setLayoutManager(new LinearLayoutManager(this));
- 初始化
questionList的时候只放了第0个父对象?检查下你的数据源,确保所有要展示的父Question都在列表里。如果是动态加载父列表,用notifyItemInserted()来添加新Item,别重建适配器。
额外小技巧
- 如果需要子列表展开/收起的功能,可以给父Item加点击事件,控制子RecyclerView的
visibility(GONE/VISIBLE),记得在适配器里保存每个父Item的展开状态,避免滚动后状态丢失。 - 数据量大的话,用
DiffUtil来优化更新性能,减少不必要的视图刷新。
内容的提问来源于stack exchange,提问作者Ajay Mehta
相关产品推荐
相关产品推荐

