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

Activity/Fragment重建(屏幕旋转)Paging3列表重复加载问题排查

问题根因

你代码的核心问题出在ViewModel中cachedIn方法的调用逻辑错误:
PagingRx.cachedIn() 是返回新的带缓存能力的Flowable实例,你当前代码没有将返回值赋值给类成员flowable,等于缓存配置完全没有生效。每次Fragment因为旋转重建重新订阅flowable时,都会触发Pager重新创建PagingSource、从头加载数据。

修复方案

修改ViewModel的init()方法,将cachedIn的返回值赋值给flowable:

private void init() {
    CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(this);
    Pager<Integer, Book> pager = new Pager<>(
            pagingConfig,
            () -> new BooksPagingSource(dataApi, preferencesHelper)
    );

    flowable = PagingRx.getFlowable(pager);
    // 注意这里要把cachedIn的返回值赋值给flowable
    flowable = PagingRx.cachedIn(flowable, viewModelScope);
}

修改后,PagingData会被缓存在ViewModel的生命周期内,旋转屏幕时ViewModel不会销毁,Fragment重建后重新订阅flowable会直接拿到已缓存的分页数据,不会触发重新加载,列表滚动位置也会自动保留。

getRefreshKey()调用场景说明

这个方法仅在PagingSource需要失效重建、整体刷新数据时才会被调用,常见触发场景包括:

  • 手动调用PagingDataAdapter.refresh()触发下拉刷新
  • 调用PagingSource.invalidate()主动让当前数据源失效
  • 分页配置变更需要重新加载数据
    它的作用是根据当前列表的浏览位置计算刷新的起始页码,保证刷新后列表不会跳回第一页,而是停在用户之前浏览的位置附近。你当前的getRefreshKey实现是符合要求的,不需要修改。

可选优化

你当前在Fragment中用requireActivity()获取ViewModel,意味着这个ViewModel的生命周期和Activity绑定,如果这个列表只在当前Fragment使用,建议改为Fragment级别的ViewModel,避免内存浪费:

// 把requireActivity()换成this,也就是Fragment自身
BooksViewModel viewModel = new ViewModelProvider(this).get(BooksViewModel.class);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 15:06:06