屏幕旋转时RecyclerView未恢复,onBindViewHolder未触发问题
解决RecyclerView旋转后onBindViewHolder不调用的问题
看起来你已经搞定了数据保存,但旋转后列表还是不渲染,核心问题大概率是Adapter初始化或RecyclerView配置的环节漏了步骤,我帮你梳理几个关键排查点和修复方案:
1. 给Adapter添加支持已有数据集的构造函数
你的当前构造函数里直接new ArrayList<Words>()创建空数据集,旋转重建Fragment时,新的Adapter实例根本拿不到你保存的旧数据——哪怕你在其他地方存了数据,Adapter内部的mDataSet还是空的(你说确认列表非空,可能是指保存的数据源非空,但没传递给新Adapter?)。
修改构造函数,让它可以接收恢复的数据集:
public CustomAdapter(RecyclerView recyclerView, Context context, TranslateActivityFragment fragment, ArrayList<Words> savedDataSet){ mRecyclerView = recyclerView; // 优先用传入的已保存数据,没有再新建空列表 mDataSet = savedDataSet != null ? savedDataSet : new ArrayList<>(); mFragment = fragment; View v = LayoutInflater.from(mFragment.getActivity()).inflate(R.layout.edit_translate,null,false); createPopupWindow(v, mFragment.getActivity()); setEditText(v); }
2. 重建Fragment时,必须重新配置RecyclerView
旋转后Fragment的视图会完全重建,旧的RecyclerView实例已经失效,你得在onViewCreated或onCreateView里重新绑定:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.your_fragment_layout, container, false); mRecyclerView = view.findViewById(R.id.your_recycler_view_id); // 关键!必须重新设置LayoutManager,没有它RecyclerView不会渲染任何内容 mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); // 从savedInstanceState恢复数据 ArrayList<Words> restoredData = null; if (savedInstanceState != null) { restoredData = savedInstanceState.getParcelableArrayList("words_data"); } // 创建Adapter时传入恢复的数据 mAdapter = new CustomAdapter(mRecyclerView, getContext(), this, restoredData); mRecyclerView.setAdapter(mAdapter); return view; }
3. 确保数据恢复后触发Adapter更新
如果你的恢复逻辑是逐个调用addData,那addData里的notifyDataSetChanged已经能触发更新;但如果是直接替换整个数据集,建议给Adapter加个批量更新的方法:
public void setDataSet(ArrayList<Words> newDataSet) { mDataSet.clear(); mDataSet.addAll(newDataSet); notifyDataSetChanged(); // 一次性通知数据变化,比逐个add更高效 }
然后在恢复数据后调用:
mAdapter.setDataSet(restoredData);
4. 检查Words类的序列化实现
你用onSaveInstanceState保存数据时,Words必须实现Parcelable或Serializable,否则数据无法正确写入Bundle。比如实现Parcelable:
public class Words implements Parcelable { private String w1; private String w2; // 构造函数、getter/setter... // Parcelable相关方法 protected Words(Parcel in) { w1 = in.readString(); w2 = in.readString(); } public static final Creator<Words> CREATOR = new Creator<Words>() { @Override public Words createFromParcel(Parcel in) { return new Words(in); } @Override public Words[] newArray(int size) { return new Words[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(w1); dest.writeString(w2); } }
最后排查小细节
- 去掉构造函数里多余的
notifyDataSetChanged():刚初始化时数据集是空的,这个通知毫无意义,反而可能干扰后续的正常更新。 - 在
getItemCount()里打Log,确认旋转后返回的size大于0:如果size是0,说明数据根本没传到Adapter里;如果size大于0但还是不渲染,那大概率是没设置LayoutManager。
按这个流程走,应该能解决onBindViewHolder不调用的问题。
内容的提问来源于stack exchange,提问作者El_Loco
相关产品推荐
相关产品推荐

