分页库:如何将一个分页列表转换为另一个具有不同大小的分页列表?



目前,我们在 Room SQLite 中存储了一个数据结构,名为Todo

我们目前的工作流程如下

  1. 道回来了DataSource.Factory<Integer, Todo>
  2. 使用LivePagedListBuilderDataSource.Factory<Integer, Todo>变成LiveData<PagedList<Todo>>
  3. 观察LiveData<PagedList<Todo>>,并使用submitListPagedList<Todo>传递给PagedListAdapter<Todo, TodoAdapter.ViewHolder>

到目前为止,对于如此简单的用例来说很好。

但是,现在,我们有更复杂的 UI 要求。我们需要先将Todo转换为TransformedTodo,然后再submitListPagedListAdapter

下面是我们的转换函数。

List<TransformedTodo> transform(Todo todo)

注意,可以将 1Todo转换为 1 或多个TransformedTodo

我最初计划的工作流程是

  1. 道回来了DataSource.Factory<Integer, Todo>
  2. 使用DataSource.Factory.mapByPageDataSource.Factory<Integer, Todo>转换为DataSource.Factory<Integer, TransformedTodo>
  3. 使用LivePagedListBuilderDataSource.Factory<Integer, TransformedTodo>变成LiveData<PagedList<TransformedTodo>>
  4. 观察LiveData<PagedList<TransformedTodo>>,并使用submitListPagedList<TransformedTodo>传递给PagedListAdapter<TransformedTodo, TodoAdapter.ViewHolder>

棘手的部分是第 2 步。

如果转换函数返回其大小与输入List<Todo>不同的输出List<TransformedTodo>,则会抛出异常。

todosDataSourceFactory.mapByPage(new Function<List<Todo>, List<TransformedTodo>>() {
@Override
public List<TransformedTodo> apply(List<Todo> input) {
// Exception will be thrown if we are returning a List where its size is different from input.
}
});

抛出的异常看起来像

java.lang.IllegalStateException: 无效函数 com.yocto.wetodo.repository.TodoRepository$1@17b6f1b 更改返回 大小。不支持此操作。

原因如下

// androidx.paging.DataSource
static <A, B> List<B> convert(Function<List<A>, List<B>> function, List<A> source) {
List<B> dest = function.apply(source);
if (dest.size() != source.size()) {
throw new IllegalStateException("Invalid Function " + function
+ " changed return size. This is not supported.");
}
return dest;
}

似乎是分页库的限制。有没有办法将一个PagedList转换为另一个不同大小的PagedList


参考链接 :

https://issuetracker.google.com/issues/142890117

如何使用列表大小不同于文件室数据库返回的列表大小的 AAC 分页库

TL;博士

我创建了一个库来允许分页库的数据源页面突变。


这里的问题是分页库mapByPage被认为返回与输入项目相同数量的项目。为了能够返回与输入不同的项目数,需要一个自定义的变异函数。

在继续之前需要注意的另一件重要事情,尤其是在使用Room时,DataSource.Factory<Key, Value>实际上最终会生成一个PositionalDataSource.与ItemKeyedDataSourcePageKeyedDataSource不同,它要求生成的页面项遵循定义的页面大小。因此,即使我们创建一个类似mapByPage的函数来允许其项目突变,接受不同的返回列表大小,在使用PositionalDataSource时仍然会导致问题,因为它不允许此列表大小修改。

可以解决此问题的解决方案是将PositionalDataSource包装在两种静止数据源类型中的另一种中,这些类型允许使用非固定页面大小,并使其表现得好像它实际上是一个PositionalDataSource

一旦我们有一个非固定的页面大小兼容"PositionalDataSource",我们就可以添加类似mapByPage的突变函数。

我实际上已经创建了一个简单的可变数据源库,它正是这样做的。它将PositionalDataSource包裹在一个行为相同的PageKeyedDataSource中。然后,可以应用mutateByPage功能,允许更改生成的项目,甚至更改列表大小或项目类型。此外,我还添加了对改变ItemKeyedDataSourcePageKeyedDataSource的支持。

请记住,此库仍可能包含错误,因此请随时报告任何问题或做出贡献。

最新更新