PagedListAdapter在接收到新的PagedList时跳到列表的开头 [英] PagedListAdapter jumps to beginning of the list on receiving new PagedList
问题描述
我正在使用分页库使用 ItemKeyedDataSource
从网络加载数据。提取项目后,用户可以对其进行编辑,此更新将在内存缓存中完成(不使用任何数据库,例如Room)。
I'm using Paging Library to load data from network using ItemKeyedDataSource
. After fetching items user can edit them, this updates are done inside in Memory cache (no database like Room is used).
PagedList
本身无法更新(在 PagedList
并将其传递给 PagedListAdapter
。
Now since the PagedList
itself cannot be updated (discussed here) I have to recreate PagedList
and pass it to the PagedListAdapter
.
更新本身没有问题,但是在使用新的 PagedList
更新了 recyclerView
之后,列表会跳到列表的开头,从而破坏上一个滚动位置。是否有在保持滚动位置的同时更新PagedList的方法(例如它如何与 Room 一起使用)?
The update itself is no problem but after updating the recyclerView
with the new PagedList
, the list jumps to the beginning of the list destroying previous scroll position. Is there anyway to update PagedList while keeping scroll position (like how it works with Room)?
DataSource 是这样实现:
public class MentionKeyedDataSource extends ItemKeyedDataSource<Long, Mention> {
private Repository repository;
...
private List<Mention> cachedItems;
public MentionKeyedDataSource(Repository repository, ..., List<Mention> cachedItems){
super();
this.repository = repository;
this.teamId = teamId;
this.inboxId = inboxId;
this.filter = filter;
this.cachedItems = new ArrayList<>(cachedItems);
}
@Override
public void loadInitial(@NonNull LoadInitialParams<Long> params, final @NonNull ItemKeyedDataSource.LoadInitialCallback<Mention> callback) {
Observable.just(cachedItems)
.filter(() -> return cachedItems != null && !cachedItems.isEmpty())
.switchIfEmpty(repository.getItems(..., params.requestedLoadSize).map(...))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(response -> callback.onResult(response.data.list));
}
@Override
public void loadAfter(@NonNull LoadParams<Long> params, final @NonNull ItemKeyedDataSource.LoadCallback<Mention> callback) {
repository.getOlderItems(..., params.key, params.requestedLoadSize)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(response -> callback.onResult(response.data.list));
}
@Override
public void loadBefore(@NonNull LoadParams<Long> params, final @NonNull ItemKeyedDataSource.LoadCallback<Mention> callback) {
repository.getNewerItems(..., params.key, params.requestedLoadSize)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(response -> callback.onResult(response.data.list));
}
@NonNull
@Override
public Long getKey(@NonNull Mention item) {
return item.id;
}
}
PagedList 创建如下
PagedList.Config config = new PagedList.Config.Builder()
.setPageSize(PAGE_SIZE)
.setInitialLoadSizeHint(preFetchedItems != null && !preFetchedItems.isEmpty()
? preFetchedItems.size()
: PAGE_SIZE * 2
).build();
pagedMentionsList = new PagedList.Builder<>(new MentionKeyedDataSource(mRepository, team.id, inbox.id, mCurrentFilter, preFetchedItems)
, config)
.setFetchExecutor(ApplicationThreadPool.getBackgroundThreadExecutor())
.setNotifyExecutor(ApplicationThreadPool.getUIThreadExecutor())
.build();
PagedListAdapter 创建如下:
public class ItemAdapter extends PagedListAdapter<Item, ItemAdapter.ItemHolder> { //Adapter from google guide, Nothing special here.. }
mAdapter = new ItemAdapter(new DiffUtil.ItemCallback<Mention>() {
@Override
public boolean areItemsTheSame(Item oldItem, Item newItem) {
return oldItem.id == newItem.id;
}
@Override
public boolean areContentsTheSame(Item oldItem, Item newItem) {
return oldItem.equals(newItem);
}
});
,并像这样更新:
mAdapter.submitList(pagedList);
推荐答案
您应该在可观察对象上使用阻塞调用。如果您不在与 loadInitial
, loadAfter
或 loadBefore相同的线程中提交结果
,发生的事情是,适配器将首先针对一个空列表,然后针对新加载的项目,计算现有列表项的 diff
。如此有效,就好像所有项目都被删除然后再次插入一样,这就是列表似乎跳到开头的原因。
You should use a blocking call on your observable. If you don't submit the result in the same thread as loadInitial
, loadAfter
or loadBefore
, what happens is that the adapter will compute the diff
of the existing list items against an empty list first, and then against the newly loaded items. So effectively it's as if all items were deleted and then inserted again, that is why the list seems to jump to the beginning.
这篇关于PagedListAdapter在接收到新的PagedList时跳到列表的开头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!