ViewHolder returns RecyclerView 中的旧位置

ViewHolder returns the old position in RecyclerView

我有一个 FragmentBottomSheet 行为,其中包含水平 RecyclerViewRecyclerView通过SnapHelper调整,实现一个页面效果。它看起来像这样:

FragmentonCreateView事件中,我设置了Adapter布局管理器:

recycler_view.setAdapter(new MyRecyclerAdapter(getContext(), dataList));
recycler_view.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));

我设置Adapter后,onCreateViewHolder事件在MyRecyclerAdapter中被触发class对象,后面是onBindViewHolder:

@Override
public MyRecyclerAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = inflater.inflate(R.layout.fragment_recycler_item, parent, false);
    return new MyViewHolder(view, parent);
}

@Override
public void onBindViewHolder(MyRecyclerAdapter.MyViewHolder viewHolder, int position) {
    /**I do something using position**/
}

当我第一次创建这个 Fragment 并配置 RecyclerView 时,一切正常,onBindViewHolder returns 正确的位置。但是当我翻转到第一个、第二个等元素 RecyclerView,然后重新创建片段时,出于某种未知原因 onBindViewHolder return 旧的(最后一个)位置,尽管创建了新的 AdapterLineraLayoutManager

为了清楚起见,我将把它分成几个步骤:

  1. 正在创建一个片段
  2. 正在创建 MyRecyclerAdapter 的对象 class。在RecyclerView.
  3. 中设置
  4. 正在创建 LinearLayoutManager 的对象 class。在RecyclerView.
  5. 中设置
  6. 触发了MyRecyclerAdapter中的onBindViewHolder事件。我得到 position = 0.
  7. 我滚动到 position = 2 的元素。
  8. 我确实分离了这个片段,然后立即附加了这个片段。
  9. 正在创建 MyRecyclerAdapter 的对象 class。在RecyclerView.
  10. 中设置
  11. 正在创建 LinearLayoutManager 的对象 class。在RecyclerView.
  12. 中设置
  13. 触发了MyRecyclerAdapter中的onBindViewHolder事件。我得到 position = 2.

问题:为什么我得到的是旧位置,最重要的是我该如何修复它?

我读到 Android 专门保存旧的 ViewHolder 以更有效地使用内存,但我不需要它。

UPD(解决方案): 在我看来,这是一个临时解决方案(不理想),但它有效。安装 AdapterLayoutManager 后,您需要 运行 smoothScrollToPosition(0)。使用smoothScrollToPosition(0)非常重要,而不是scrollToPosition(0):

recycler_view.setAdapter(new MyRecyclerAdapter(getContext(), dataList));
recycler_view.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
recycler_view.smoothScrollToPosition(0);

UPD.1(最佳解决方案) 只需使用:

recyclerView.setSaveEnabled(false);

是 Android 自动保存旧的 ViewHolder 以更有效地使用内存。

如果你不需要。

然后再次设置适配器或执行 notifyDataSetChanged();

如果您分离并重新附加片段,则只会销毁和重新创建其视图层次结构。恢复滚动位置是 RecyclerView 状态恢复行为的一部分。

如果您希望 RecyclerView 始终从滚动 0 开始,您可以通过禁用该行为来防止它首先保存其滚动状态:

recyclerView.setSaveEnabled(false);