【问题标题】:ViewHolder returns the old position in RecyclerViewViewHolder 返回 RecyclerView 中的旧位置
【发布时间】:2020-05-30 00:31:49
【问题描述】:

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

FragmentonCreateView事件中,我设置了AdapterLayoutManager

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

我设置Adapter后,MyRecyclerAdapter类对象中触发onCreateViewHolder事件,接着是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 返回正确的位置。但是当我翻转到第一个、第二个等元素 RecyclerView,然后重新创建片段时,由于某种未知原因 onBindViewHolder 返回旧的(最后一个)位置,虽然新的 AdapterLineraLayoutManager 已创建。

为了清楚起见,我将其分解为几个步骤:

  1. 创建一个片段
  2. 创建MyRecyclerAdapter 类的对象。在RecyclerView中设置它。
  3. 创建LinearLayoutManager 类的对象。在RecyclerView中设置它。
  4. MyRecyclerAdapter中的onBindViewHolder 事件被触发。我得到 position = 0
  5. 我滚动到 position = 2 的元素。
  6. 我确实分离了这个片段,然后立即附加这个片段。
  7. 创建MyRecyclerAdapter 类的对象。在RecyclerView中设置它。
  8. 创建LinearLayoutManager 类的对象。在RecyclerView中设置它。
  9. 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 android-fragments android-recyclerview android-viewholder


    【解决方案1】:

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

    如果你不需要。

    然后重新设置适配器或执行 notifyDataSetChanged();

    【讨论】:

    • 我在步骤 7 中再次设置适配器,但没有帮助。我找到了解决方案并将其添加到我的问题中。
    【解决方案2】:

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

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

    recyclerView.setSaveEnabled(false);
    

    【讨论】:

    • 非常感谢您提供如此简单方便的解决方案!
    猜你喜欢
    • 2017-08-11
    • 2020-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多