不使用房间更新PagingLibrary中的列表项(仅网络) [英] Update list items in PagingLibrary w/o using Room (Network only)

本文介绍了不使用房间更新PagingLibrary中的列表项(仅网络)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用分页库使用 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);

PS:如果有更好的方法来更新列表项而不使用Room,请共享。

P.S: If there is a better way to update list items without using Room please share.

推荐答案

您需要做的就是每次更新您的当前 DataSource 均无效数据。

All you need to do is to invalidate current DataSource each time you update your data.

我要做什么:


  • 移动网络逻辑从 MentionKeyedDataSource 到扩展 PagedList.BoundaryCallback 的新类,并在构建 PagedList <时进行设置/ code>。

  • move networking logic from MentionKeyedDataSource to new class that extends PagedList.BoundaryCallback and set it when building your PagedList.

将所有数据移动到保存所有下载内容的 DataProvider 数据,并引用了 DataSource 。每次在 DataProvider 中更新数据时,都会使当前的 DataSource

move all you data to some DataProvider that holds all your downloaded data and has reference to DataSource. Each time data is updated in DataProvider invalidate current DataSource

类似的东西

    val dataProvider = PagedDataProvider()
    val dataSourceFactory = InMemoryDataSourceFactory(dataProvider = dataProvider)

其中

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

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

此方法与 Room 的操作非常相似-每次更新表行-当前 DataSource 无效,并且 DataSourceFactory 创建新的数据源。

This approach is very similar to what Room does - every time table row is updated - current DataSource is invalidated and DataSourceFactory creates new data source.

这篇关于不使用房间更新PagingLibrary中的列表项(仅网络)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆