gpt4 book ai didi

android - 分页库使数据源无效不起作用

转载 作者:行者123 更新时间:2023-12-02 01:47:41 25 4
gpt4 key购买 nike

最近我正在尝试这个:

我有一个由数据源支持的作业列表(我正在使用分页库),作业列表中的每个项目都有一个保存按钮,该保存按钮将作业的状态从未保存更新为已保存(反之亦然) )在数据库中,一旦更新它就会使数据源失效,现在失效应该会导致当前页面立即重新加载,但这种情况并没有发生。

我检查了数据库中的值,它们实际上已更新,但 UI 的情况并非如此。

代码:

public class JobsPagedListProvider {

private JobListDataSource<JobListItemEntity> mJobListDataSource;

public JobsPagedListProvider(JobsRepository jobsRepository) {
mJobListDataSource = new JobListDataSource<>(jobsRepository);
}

public LivePagedListProvider<Integer, JobListItemEntity> jobList() {
return new LivePagedListProvider<Integer, JobListItemEntity>() {
@Override
protected DataSource<Integer, JobListItemEntity> createDataSource() {
return mJobListDataSource;
}
};
}

public void setQueryFilter(String query) {
mJobListDataSource.setQuery(query);
}
}

这是我的自定义数据源:

public class JobListDataSource<T> extends TiledDataSource<T> {

private final JobsRepository mJobsRepository;
private final InvalidationTracker.Observer mObserver;


String query = "";

@Inject
public JobListDataSource(JobsRepository jobsRepository) {
mJobsRepository = jobsRepository;

mJobsRepository.setJobListDataSource(this);

mObserver = new InvalidationTracker.Observer(JobListItemEntity.TABLE_NAME) {
@Override
public void onInvalidated(@NonNull Set<String> tables) {
invalidate();
}
};

jobsRepository.addInvalidationTracker(mObserver);
}

@Override
public boolean isInvalid() {
mJobsRepository.refreshVersionSync();
return super.isInvalid();
}

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

以下是 JobsRepository 中将作业从未保存更新为已保存的代码:

public void saveJob(JobListItemEntity entity) {
Completable.fromCallable(() -> {
JobListItemEntity newJob = new JobListItemEntity(entity);
newJob.isSaved = true;
mJobDao.insert(newJob);
Timber.d("updating entity from " + entity.isSaved + " to "
+ newJob.isSaved); //this gets printed in log
//insertion in db is happening as expected but UI is not receiving new list
mJobListDataSource.invalidate();
return null;
}).subscribeOn(Schedulers.newThread()).subscribe();
}

这是作业列表的比较逻辑:

private static final DiffCallback<JobListItemEntity> DIFF_CALLBACK =  new DiffCallback<JobListItemEntity>() {
@Override
public boolean areItemsTheSame(@NonNull JobListItemEntity oldItem, @NonNull JobListItemEntity newItem) {
return oldItem.jobID == newItem.jobID;
}

@Override
public boolean areContentsTheSame(@NonNull JobListItemEntity oldItem, @NonNull JobListItemEntity newItem) {
Timber.d(oldItem.isSaved + " comp with" + newItem.isSaved);
return oldItem.jobID == newItem.jobID
&& oldItem.jobTitle.compareTo(newItem.jobTitle) == 0
&& oldItem.isSaved == newItem.isSaved;
}
};

JobRepository 中的 JobListDataSource(下面仅提及相关部分):

public class JobsRepository {
//holds an instance of datasource
private JobListDataSource mJobListDataSource;

//setter
public void setJobListDataSource(JobListDataSource jobListDataSource) {
mJobListDataSource = jobListDataSource;
}

}

JobsRepository 中的 getJobs():

public List<JobListItemEntity> getJobs(String query, int startPosition, int count) {
if (!isJobListInit) {

Observable<JobList> jobListObservable = mApiService.getOpenJobList(
mRequestJobList.setPageNo(startPosition/count + 1)
.setMaxResults(count)
.setSearchKeyword(query));

List<JobListItemEntity> jobs = mJobDao.getJobsLimitOffset(count, startPosition);

//make a synchronous network call since we have no data in db to return
if(jobs.size() == 0) {
JobList jobList = jobListObservable.blockingSingle();
updateJobList(jobList, startPosition);
} else {
//make an async call and return cached version meanwhile
jobListObservable.subscribe(new Observer<JobList>() {
@Override
public void onSubscribe(Disposable d) {

}

@Override
public void onNext(JobList jobList) {
updateJobList(jobList, startPosition);
}

@Override
public void onError(Throwable e) {
Timber.e(e);
}

@Override
public void onComplete() {

}
});
}
}

return mJobDao.getJobsLimitOffset(count, startPosition);
}

更新jobsRepository中的JobList:

private void updateJobList(JobList jobList, int startPosition) {
JobListItemEntity[] jobs = jobList.getJobsData();
mJobDao.insert(jobs);
mJobListDataSource.invalidate();
}

最佳答案

阅读 DataSource 的源代码后我意识到:

  1. 数据源一旦失效将永远不会再次有效。
  2. invalidate()说:如果已经调用了 invalidate,则此方法不执行任何操作。

我实际上有一个由 JobListDataSource 提供的自定义数据源 ( JobsPagedListProvider ) 的单例,所以当我使我的 DataSource 无效时在saveJob() (在 JobsRepository 中定义),它试图获取新的 DataSource实例(通过再次调用 loadRange() 来获取最新数据 - 这就是刷新数据源的工作原理)但自从我的DataSource是单例,它已经无效,所以没有 loadRange()正在查询!

因此请确保您没有 DataSource 的单例并使您的 DataSource 无效手动(通过调用 invalidate() )或使用 InvalidationTracker在您的数据源的构造函数中。

所以最终的解决方案是这样的:

JobsPagedListProvider 中没有单例:

public class JobsPagedListProvider {

private JobListDataSource<JobListItemEntity> mJobListDataSource;

private final JobsRepository mJobsRepository;

public JobsPagedListProvider(JobsRepository jobsRepository) {
mJobsRepository = jobsRepository;
}

public LivePagedListProvider<Integer, JobListItemEntity> jobList() {
return new LivePagedListProvider<Integer, JobListItemEntity>() {
@Override
protected DataSource<Integer, JobListItemEntity> createDataSource() {
//always return a new instance, because if DataSource gets invalidated a new instance will be required(that's how refreshing a DataSource works)
mJobListDataSource = new JobListDataSource<>(mJobsRepository);
return mJobListDataSource;
}
};
}

public void setQueryFilter(String query) {
mJobListDataSource.setQuery(query);
}
}

还要确保,如果您从网络获取数据,则需要有正确的逻辑来在查询网络之前检查数据是否过时,否则每次数据源失效时都会重新查询。我通过在JobEntity中有一个insertedAt字段解决了这个问题它跟踪该项目何时插入数据库并检查它是否在 getJobs() 中过时。的JobsRepository

以下是 getJobs() 的代码:

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 (shouldRefetchJobList(jobs)) {
//data available in db, so show a cached version and make async network call to update data
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);
}

最后删除 JobListDatasource 中的 InvalidationTracker,因为我们手动处理失效:

public class JobListDataSource<T> extends TiledDataSource<T> {

private final JobsRepository mJobsRepository;

String query = "";

public JobListDataSource(JobsRepository jobsRepository) {
mJobsRepository = jobsRepository;
mJobsRepository.setJobListDataSource(this);
}

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

关于android - 分页库使数据源无效不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46794006/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com