分页库 - 在从网络请求时从缓存填充

时间:2017-10-14 14:59:45

标签: android caching android-architecture-components

我必须从数据库加载缓存版本的数据,同时我想向服务器请求新数据,我想在每页上执行此操作。 因此,例如对于第一页,我想要从数据库显示第一页数据的缓存版本,同时仅为第一页请求新数据。
我想用Paging Library实现这一目标。
我尝试创建自定义数据源,帮助我拦截页面加载请求,然后我用来进行网络调用所需的页码和限制,同时我从db返回一个缓存版本,问题是从网络获取新数据后我更新了数据库,但没有反映这些更新。
(我相信使用Invalidation Tracker进行任何修改都会观察到整个表格,并且每当表格无效时数据源都会失效,我在我的数据源中添加了跟踪器但仍然无法正常工作;我能够弄清楚通过在JobDao中临时创建:LivePagedListProvider getJobs()并检查生成的实现来实现Invalidation Tracker的事情

代码:

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);
}

1 个答案:

答案 0 :(得分:0)

所以我理解为什么它不起作用,我的结果出现了错误,我在JobRepository中将错误的参数传递给JobDao的getJobs方法。

JobDao的getJobs方法如下:

@Query("SELECT * FROM jobs ORDER BY jobID ASC LIMIT :limit OFFSET :offset")
List<JobEntity> getJobs(int limit, int offset);

JobRepository中的调用getJobs()如下:

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();
    }
}

(我还将JobDao中的getJobs()重命名为getJobsLimitOffset(),因为它使其更具可读性,这也是分页库生成方法的方式)