【问题标题】:Paging library : How to transform a PagedList to another PagedList with different size?分页库:如何将一个 PagedList 转换为另一个不同大小的 PagedList?
【发布时间】:2020-05-31 17:37:35
【问题描述】:

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

我们目前的工作流程如下

  1. Dao 正在返回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,然后将submitList 转换为PagedListAdapter

这是我们的变换函数。

List<TransformedTodo> transform(Todo todo)

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

我最初计划的工作流程是

  1. 道正在返回DataSource.Factory&lt;Integer, Todo&gt;
  2. 使用DataSource.Factory.mapByPage,将DataSource.Factory&lt;Integer, Todo&gt; 转换为DataSource.Factory&lt;Integer, TransformedTodo&gt;
  3. 使用LivePagedListBuilderDataSource.Factory&lt;Integer, TransformedTodo&gt; 变成LiveData&lt;PagedList&lt;TransformedTodo&gt;&gt;
  4. 观察LiveData&lt;PagedList&lt;TransformedTodo&gt;&gt;,并使用submitListPagedList&lt;TransformedTodo&gt;传递给PagedListAdapter&lt;TransformedTodo, TodoAdapter.ViewHolder&gt;

棘手的部分是第 2 步。

如果转换函数返回输出List&lt;TransformedTodo&gt;,其大小与输入List&lt;Todo&gt;不同,则会抛出异常。

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

How to use AAC paging library with list size different than list size returned by Room database

【问题讨论】:

    标签: android android-architecture-components android-paging


    【解决方案1】:

    TL;DR

    我创建了一个library 以允许分页库 的DataSources 页面突变。


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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多