You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ViewPager滑动切换Fragment时RecyclerView Adapter数据丢失异常排查

问题分析与解决方案

核心原因

FragmentStatePagerAdapter(及ViewPager2的FragmentStateAdapter)会自动销毁非活跃的Fragment(默认保留当前页前后各1个),当Fragment被重建时,RecyclerView的Adapter可能与当前Fragment的数据源imageSet引用脱节:

  • 原Adapter持有的是旧Fragment中数据源的引用,重建后的Fragment里imageSet是新实例,导致Adapter的getItemCount()返回0,但当前Fragment的imageSet实际有数据;
  • 若Fragment重建时未正确恢复数据源,或Adapter未同步更新引用,滚动RecyclerView时就会触发IndexOutOfBound异常。

你的临时方案(重新设置Adapter)有效,本质是让RecyclerView重新绑定当前Fragment的imageSet数据源,但这不是最优解,以下是更合理的处理方式:


具体解决方案

1. 让RecyclerView Adapter持有数据源的实时引用

不要在Adapter初始化时拷贝数据源,而是直接持有引用,并提供更新方法同步数据:

public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder> {
    private List<String> mImageData;

    // 构造方法传入数据源引用
    public ImageAdapter(List<String> imageData) {
        this.mImageData = imageData;
    }

    // 提供更新数据源的方法
    public void updateData(List<String> newData) {
        this.mImageData = newData;
        notifyDataSetChanged(); // 通知RecyclerView刷新
    }

    @Override
    public int getItemCount() {
        return mImageData == null ? 0 : mImageData.size();
    }

    // ViewHolder及绑定逻辑省略
}

2. 在Fragment恢复时同步Adapter数据源

在Fragment的onResume或onViewCreated中,复用已有Adapter并更新其数据源,而非每次重建都新建Adapter:

private ImageAdapter mImageAdapter;
private List<String> imageSet;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_image_list, container, false);
    RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    
    // 初始化Adapter,绑定当前imageSet
    mImageAdapter = new ImageAdapter(imageSet);
    recyclerView.setAdapter(mImageAdapter);
    return view;
}

@Override
public void onResume() {
    super.onResume();
    // 确保Adapter数据源与当前Fragment的imageSet同步
    if (mImageAdapter != null) {
        mImageAdapter.updateData(imageSet);
    }
}

3. 确保Fragment重建时数据源正确恢复

当Fragment因ViewPager销毁重建时,通过onSaveInstanceState保存数据源,在onCreate中恢复:

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    // 保存当前数据源
    outState.putStringArrayList("image_set", new ArrayList<>(imageSet));
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        // 恢复之前保存的数据源
        imageSet = savedInstanceState.getStringArrayList("image_set");
    } else {
        // 首次创建时加载初始数据
        imageSet = loadInitialImageData();
    }
}

4. ViewPager2的适配处理

ViewPager2使用FragmentStateAdapter,销毁重建逻辑与ViewPager一致,只需沿用上述Adapter和Fragment的处理方式即可,无需额外修改。


为什么临时方案有效?

重新设置Adapter相当于为RecyclerView绑定了当前Fragment最新的imageSet引用,让getItemCount()能正确返回数据量。但频繁创建Adapter会导致不必要的对象开销,复用Adapter并更新数据的方式性能更优。

内容的提问来源于stack exchange,提问作者MJM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 21:45:33