使用Paging3+Guava/LiveData时LiveData提前触发且不再更新求助
问题分析与解决方案
你的问题核心在于ListenableFuturePagingSource返回的LoadResult.Page未正确设置prevKey,同时线程池管理不当,导致Paging3无法正确构建分页数据链,进而无法触发LiveData的后续更新。以下是具体修复步骤:
1. 正确设置LoadResult.Page的prevKey
当前你所有分页的prevKey都设为null,这会导致Paging3无法正确跟踪分页的前后依赖关系,无法将新加载的数据合并到PagingData中,自然不会触发LiveData的onChanged回调。修改loadFuture中的返回逻辑:
@Override public LoadResult<Integer, Product> call() { List<Product> productsList = productsRepository.loadProducts(loadParams.getLoadSize(), finalOffSet); Integer nextKey = productsList.size() >= loadParams.getLoadSize() ? finalNextPageNumber + 1 : null; // 正确设置prevKey:当前页大于1时,prevKey为当前页减1 Integer prevKey = finalNextPageNumber > 1 ? finalNextPageNumber - 1 : null; return new LoadResult.Page<>(productsList, prevKey, nextKey); }
2. 复用线程池,避免重复创建
每次loadFuture调用时新建线程池会导致线程泄漏,且可能影响Paging对ListenableFuture回调的监听。将线程池改为ProductsPagingSource的成员变量:
public class ProductsPagingSource extends ListenableFuturePagingSource<Integer, Product> { private final ProductsRepository productsRepository; private final ListeningExecutorService service; private Integer initialLoadSize = 0; public ProductsPagingSource(ProductsRepository productsRepository) { this.productsRepository = productsRepository; // 复用固定大小的线程池 this.service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(2)); } // ... 其他方法不变,loadFuture中直接使用this.service }
3. 简化Offset计算逻辑
原逻辑过于复杂,容易出错,简化为更直观的写法:
Integer nextPageNumber = loadParams.getKey(); if (nextPageNumber == null) { nextPageNumber = 1; initialLoadSize = loadParams.getLoadSize(); } // 简化offset计算 Integer offset; if (nextPageNumber == 1) { offset = 0; } else { // 初始加载的size + 后续每页的size累加 offset = initialLoadSize + (nextPageNumber - 2) * loadParams.getLoadSize(); }
4. 完善getRefreshKey实现(可选但推荐)
返回合适的刷新key,确保下拉刷新时能从正确的位置加载数据:
@Nullable @Override public Integer getRefreshKey(@NonNull PagingState<Integer, Product> pagingState) { Integer anchorPosition = pagingState.getAnchorPosition(); if (anchorPosition == null) { return null; } PagingSource.LoadResult.Page<Integer, Product> anchorPage = pagingState.closestPageToPosition(anchorPosition); if (anchorPage == null) { return null; } // 优先基于prevKey计算刷新key,没有则用nextKey if (anchorPage.getPrevKey() != null) { return anchorPage.getPrevKey() + 1; } return anchorPage.getNextKey() != null ? anchorPage.getNextKey() - 1 : null; }
5. 明确配置PagingConfig(可选)
在ViewModel中创建Pager时,明确指定initialLoadSize,避免默认值(pageSize*3)带来的分页偏移问题:
Pager<Integer, Product> pager = new Pager( new PagingConfig( 10, // pageSize:每页加载数量 10, // initialLoadSize:初始加载数量 false, // enablePlaceholders:是否启用占位符 10 // prefetchDistance:预加载距离 ), () -> new ProductsPagingSource(productsRepository) );
完成以上修改后,Paging3就能正确构建分页数据链,当新数据加载完成时,LiveData会触发onChanged回调,将包含新数据的PagingData传递给Adapter。
内容的提问来源于stack exchange,提问作者Daniel Trindade
相关产品推荐
相关产品推荐

