Kei*_*ati 6 android-architecture-components android-jetpack android-paging android-architecture-paging
我正在使用Paging Library从网络加载数据ItemKeyedDataSource.在获取项目后,用户可以编辑它们,此更新在内存缓存中完成(不使用像Room这样的数据库).
现在因为它PagedList本身无法更新(这里讨论),我必须重新创建PagedList并传递给它PagedListAdapter.
更新本身没有问题,但在recyclerView使用new 更新后PagedList,列表会跳转到列表的开头,从而破坏前一个滚动位置.无论如何更新PagedList同时保持滚动位置(就像它如何与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;
}
}
Run Code Online (Sandbox Code Playgroud)
该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();
Run Code Online (Sandbox Code Playgroud)
该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);
}
});
Run Code Online (Sandbox Code Playgroud)
,并像这样更新:
mAdapter.submitList(pagedList);
Run Code Online (Sandbox Code Playgroud)
PS:如果有更好的方法来更新列表项而不使用Room请分享.
您所需要做的就是DataSource每次更新数据时使当前无效。
我会做什么:
将网络逻辑从新类移至MentionKeyedDataSource新类,PagedList.BoundaryCallback在构建PagedList.
将所有数据移动到DataProvider保存所有下载数据并引用 的某个位置DataSource。每次更新数据时都会使DataProvider当前无效DataSource
也许是这样的事情
val dataProvider = PagedDataProvider()
val dataSourceFactory = InMemoryDataSourceFactory(dataProvider = dataProvider)
Run Code Online (Sandbox Code Playgroud)
在哪里
class PagedDataProvider : DataProvider<Int, DataRow> {
private val dataCache = mutableMapOf<Int, List<DataRow>>()
override val sourceLiveData = MutableLiveData<DataSource<Int, DataRow>>()
//implement data add/remove/update here
//and after each modification call
//sourceLiveData.value?.invalidate()
}
Run Code Online (Sandbox Code Playgroud)
和
class InMemoryDataSourceFactory<Key, Value>(
private val dataProvider: DataProvider<Key, Value>
) : DataSource.Factory<Key, Value>() {
override fun create(): DataSource<Key, Value> {
val source = InMemoryDataSource(dataProvider = dataProvider)
dataProvider.sourceLiveData.postValue(source)
return source
}
}
Run Code Online (Sandbox Code Playgroud)
Room这种方法与每次更新表行时当前的行都DataSource无效并创建新的数据源非常相似DataSourceFactory。
| 归档时间: |
|
| 查看次数: |
1456 次 |
| 最近记录: |