如何强制Paging Library发起API请求刷新数据库数据?
解决PagedList.BoundaryCallback本地有数据时强制刷新网络的问题
你的问题很典型——PagedList的BoundaryCallback设计初衷就是仅在本地数据源为空(onZeroItemsLoaded)或滚动到列表末尾(onItemAtEndLoaded)时触发网络请求,所以本地已有数据时不会自动发起刷新。要实现强制刷新,我们需要给BoundaryCallback添加主动触发的逻辑,结合本地数据清理和分页重置来完成。
下面是具体的实现方案,基于你提供的代码修改:
1. 给BoundaryCallback添加手动刷新方法
修改UpcomingMoviesBoundaryCallback,新增refresh()方法,负责重置分页、清空本地旧数据并触发网络请求:
public class UpcomingMoviesBoundaryCallback extends PagedList.BoundaryCallback<MovieListItemEntity> { public static final String TAG = UpcomingMoviesBoundaryCallback.class.getSimpleName(); private UpcomingMoviesRepository upcomingMoviesRepository; private int page = 1; private boolean isRefreshing = false; // 防止并发刷新 public UpcomingMoviesBoundaryCallback(UpcomingMoviesRepository upcomingMoviesRepository) { this.upcomingMoviesRepository = upcomingMoviesRepository; } // 新增手动刷新方法 public void refresh() { if (isRefreshing) return; isRefreshing = true; page = 1; // 重置分页到第一页 // 先清空本地旧数据,确保刷新后展示最新内容 upcomingMoviesRepository.clearUpcomingMovies() .subscribeOn(Schedulers.io()) .subscribe(() -> { load(); // 清空后加载最新第一页数据 isRefreshing = false; }, error -> { Log.d(TAG, "refresh: 清空本地数据失败", error); isRefreshing = false; }); } @Override public void onZeroItemsLoaded() { super.onZeroItemsLoaded(); Log.d(TAG, "onZeroItemsLoaded: "); load(); } @Override public void onItemAtEndLoaded(@NonNull MovieListItemEntity itemAtEnd) { super.onItemAtEndLoaded(itemAtEnd); Log.d(TAG, "onItemAtEndLoaded: "); load(); } @SuppressLint("CheckResult") private void load() { upcomingMoviesRepository.getUpcoming(page) .doOnSuccess(result -> { upcomingMoviesRepository.saveUpcomingMovies(result); page = result.getPage() + 1; }) .subscribeOn(Schedulers.io()) .subscribe(result -> { Log.d(TAG, "load: 加载第" + result.getPage() + "页成功"); }, error -> { Log.d(TAG, "load: 加载失败", error); }); } }
2. 扩展Repository的功能
修改UpcomingMoviesRepositoryImpl,保存BoundaryCallback实例并新增清空本地数据、触发刷新的方法:
public class UpcomingMoviesRepositoryImpl implements UpcomingMoviesRepository { private static final String TAG = UpcomingMoviesRepository.class.getSimpleName(); private MovieResponseMapper movieResponseMapper = new MovieResponseMapper(); private MovieAppApi mMovieAppApi; private UpcomingDao mUpcomingDao; private UpcomingMoviesBoundaryCallback boundaryCallback; // 保存BoundaryCallback实例 public UpcomingMoviesRepositoryImpl(MovieAppApi mMovieAppApi, UpcomingDao mUpcomingDao) { this.mMovieAppApi = mMovieAppApi; this.mUpcomingDao = mUpcomingDao; } @Override public Single<MovieListResponse> getUpcoming(int page) { return mMovieAppApi.upcoming(page); } @Override public Single<MovieListResponse> getUpcoming() { return mMovieAppApi.upcoming(); } @Override public void saveUpcomingMovies(MovieListResponse movieListResponse) { Executors.newSingleThreadExecutor().execute(() -> { long[] inserted = mUpcomingDao.save(movieResponseMapper.map2(movieListResponse.getResults())); Log.d(TAG, "saveUpcomingMovies: 保存了" + inserted.length + "条数据"); }); } // 新增:清空本地即将上映电影数据 public Completable clearUpcomingMovies() { return Completable.fromAction(() -> mUpcomingDao.clear()) .subscribeOn(Schedulers.io()); } // 新增:触发刷新的对外接口 public void refreshUpcomingMovies() { if (boundaryCallback != null) { boundaryCallback.refresh(); } } @Override public LiveData<PagedList<MovieListItemEntity>> getUpcomingLiveData() { PagedList.Config config = new PagedList.Config.Builder() .setEnablePlaceholders(true) .setPageSize(12) .build(); DataSource.Factory<Integer, MovieListItemEntity> dataSource = mUpcomingDao.upcoming(); boundaryCallback = new UpcomingMoviesBoundaryCallback(this); // 初始化并保存实例 LivePagedListBuilder builder = new LivePagedListBuilder(dataSource, config) .setBoundaryCallback(boundaryCallback); return builder.build(); } }
3. 在Dao中添加清空数据的方法
给UpcomingDao新增清空表的SQL方法:
@Dao public interface UpcomingDao { // 原有保存、查询方法... @Query("DELETE FROM upcoming_movies") void clear(); }
4. 在业务层触发刷新
在你需要刷新的地方(比如下拉刷新的回调、页面重新可见时)调用Repository的刷新方法:
// 示例:在ViewModel中调用 public class UpcomingMoviesViewModel extends ViewModel { private final UpcomingMoviesRepository repository; private final LiveData<PagedList<MovieListItemEntity>> upcomingMovies; public UpcomingMoviesViewModel(UpcomingMoviesRepository repository) { this.repository = repository; upcomingMovies = repository.getUpcomingLiveData(); } // 对外暴露刷新方法,供UI层调用 public void refreshMovies() { repository.refreshUpcomingMovies(); } }
核心逻辑说明
- 重置分页:刷新时把
page重置为1,确保加载的是最新的第一页数据 - 清空本地数据:避免旧数据和新数据混合,保证刷新后展示的全是最新内容
- 并发控制:用
isRefreshing标记防止多次触发刷新导致的重复网络请求 - 兼容原有逻辑:刷新完成后,滑动到列表末尾依然会触发
onItemAtEndLoaded加载后续分页数据
内容的提问来源于stack exchange,提问作者Andras Sanislo
相关产品推荐
相关产品推荐

