分页库 - 在从网络请求时从缓存填充
我必须从数据库加载缓存版本的数据,同时我想向服务器请求新鲜数据,并且我希望在每页基础上执行此操作。 因此,例如对于第一页,我想要显示来自数据库的第一页数据的缓存版本,而仅请求第一页的新数据。
我想用Paging Library来实现这个。
我试图创建自定义数据源,它帮助我拦截页面加载请求,然后我用网页调用所需的页码和限制,同时我从数据库返回一个缓存版本,问题是在从网络获取新数据后我更新数据库,但这些更新没有反映出来。 (我相信使用Invalidation Tracker的任何修改都会观察整个表格,并且无论何时表格无效,数据源都会失效,但我也在数据源中添加了该跟踪器,但仍然无法使用;我能够使指出,失效跟踪的事情暂时创建:在JobDao LivePagedListProvider getJobs(),并检查生成的实现)分页库 - 在从网络请求时从缓存填充
代码:
public class JobListDataSource<T> extends TiledDataSource<T> {
private final JobsRepository mJobsRepository;
private final InvalidationTracker.Observer mObserver;
String query = "";
public JobListDataSource(JobsRepository jobsRepository) {
mJobsRepository = jobsRepository;
mObserver = new InvalidationTracker.Observer(JobEntity.TABLE_NAME) {
@Override
public void onInvalidated(@NonNull Set<String> tables) {
invalidate();
}
};
jobsRepository.addInvalidationTracker(mObserver);
}
@Override
public int countItems() {
return DataSource.COUNT_UNDEFINED;
}
@Override
public List<T> loadRange(int startPosition, int count) {
return (List<T>) mJobsRepository.getJobs(query, startPosition, count);
}
public void setQuery(String query) {
this.query = query;
}
}
职位库功能:
public List<JobEntity> getJobs(String query, int startPosition, int count) {
if (!isJobListInit) {
JobList jobList = mApiService.getOpenJobList(
mRequestJobList.setPageNo(startPosition/count + 1)
.setMaxResults(count)
.setSearchKeyword(query)
).blockingSingle();
mJobDao.insert(jobList.getJobsData());
}
return mJobDao.getJobs(startPosition, count);
}
public void addInvalidationTracker(InvalidationTracker.Observer observer) {
mAppDatabase.getInvalidationTracker().addObserver(observer);
}
所以我明白了为什么它不能正常工作,在我的最后出现了一个错误,我在JobRepository中传递了JobJO的JOB方法的错误参数。
JobDao的getJobs方法去如下:
@Query("SELECT * FROM jobs ORDER BY jobID ASC LIMIT :limit OFFSET :offset")
List<JobEntity> getJobs(int limit, int offset);
和呼叫getJobs()在JobsRepository去如下:
return mJobDao.getJobs(startPosition, count);
所以第一个参数是极限,下一个是抵消,但我是通过其他方式。
现在它就像一个魅力!
此外,我对JobsRepository中的getJobs()进行了更改: 首先从db中获取数据(如果可用)返回并根据需要向网络发出异步请求。 如果db中没有数据可用,则调用同步调用网络,从网络获取数据,解析数据并保存数据库,然后从db中获取最新数据并返回。 因此函数是这样的:
//you can even refactor this code so that all the network related stuff is in one class and just call that method
public List<JobListItemEntity> getJobs(String query, int startPosition, int count) {
Observable<JobList> jobListObservable = mApiService.getOpenJobList(
mRequestJobList.setPageNo(startPosition/count + 1)
.setMaxResults(count)
.setSearchKeyword(query));
List<JobListItemEntity> jobs = mJobDao.getJobsLimitOffset(count, startPosition);
//no data in db, make a synchronous call to network to get the data
if (jobs.size() == 0) {
JobList jobList = jobListObservable.blockingSingle();
updateJobList(jobList, startPosition, false);
} else if (shouldFetchJobList(jobs)) {
//data available in db, so show a cached version and make async network call to update data as this data is no longer fresh
jobListObservable.subscribe(new Observer<JobList>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(JobList jobList) {
updateJobList(jobList, startPosition, true);
}
@Override
public void onError(Throwable e) {
Timber.e(e);
}
@Override
public void onComplete() {
}
});
}
return mJobDao.getJobsLimitOffset(count, startPosition);
}
updateJobList()代码:
private void updateJobList(JobList jobList, int startPosition, boolean performInvalidation) {
JobListItemEntity[] jobs = jobList.getJobsData();
Date currentDate = Calendar.getInstance().getTime();
//tracks when this item was inserted in db, used in calculating whether data is stale
for (int i = 0; i < jobs.length; i++) {
jobs[i].insertedAt = currentDate;
}
mJobDao.insert(jobs);
if (performInvalidation) {
mJobListDataSource.invalidate();
}
}
(我也改名为getJobs()在JobDao到getJobsLimitOffset(),因为它使得它更具可读性,这是也是分页库生成方法的方式)