如何检查 Paging 3 库中的列表大小或空列表

Posted

技术标签:

【中文标题】如何检查 Paging 3 库中的列表大小或空列表【英文标题】:How to check the list size or for empty list in Paging 3 library 【发布时间】:2021-02-04 17:03:40 【问题描述】:

按照此处提供的说明,我已经能够成功实现新的 alpha07 版本的 Paging 3 库:https://developer.android.com/topic/libraries/architecture/paging/v3-paged-data#guava-livedata

但是,现在我需要检查返回的列表是否为空,以便向用户显示视图或文本,但我无法在其分页设计的流程结构中附加任何检查.

目前,在遵循他们的指南后,我在 onViewCreated 中使用 Java 编写代码的方式如下:

        MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);

        LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
        Lifecycle lifecycle = lifecycleOwner.getLifecycle();
        Pager<Integer, MyEntity> pager = new Pager<>(new PagingConfig(10), () -> viewModel.getMyPagingSource());
        LiveData<PagingData<MyEntity>> pagingDataLiveData = PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager), lifecycle);

        pagingDataLiveData.observe(lifecycleOwner, data -> adapter.submitData(lifecycle, data));

我尝试在adapter.submitData(lifecycle, data) 中的data 上附加.filter,但尽管列表为空,但它从未收到null 项目。

在这种情况下如何检查提交给适配器的数据何时为空?我在他们的文档中找不到任何指针。

编辑:这是我找到的解决方案,在这里发布是因为选择的答案严格来说不是解决方案,也不是 java 中的解决方案,而是引导我找到它的答案。

我必须在我的适配器上附加一个LoadStateListener,监听LoadType 何时为REFRESH 并且LoadState 为NotLoading,然后检查adapter.getItemCount 是否为0。

可能一个不同的LoadType 更适合这种情况,但到目前为止刷新对我来说是有效的,所以我选择了那个。

示例:

// somewhere when you initialize your adapter
...
myAdapter.addLoadStateListener(this::loadStateListener);
...
private Unit loadStateListener(@Nonnull CombinedLoadStates combinedLoadStates) 

    if (!(combinedLoadStates.getRefresh() instanceof LoadState.NotLoading)) 
        return Unit.INSTANCE; // this is the void equivalent in kotlin
    

    myView.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.INVISIBLE);

    return Unit.INSTANCE; // this is the void equivalent in kotlin


注意:我们必须返回 Unit.INSTANCE,因为该侦听器在 kotlin 中,并且该代码正在 java 中使用,返回它相当于在 java (void) 中不返回任何内容。

【问题讨论】:

【参考方案1】:

PagingData 运算符对单个项目进行操作,因此如果页面为空,它们不会被触发。

相反,您想在页面加载后通过观察 loadStateFlow 检查 PagingDataAdapter.itemCount。

loadStateFlow.map  it.refresh 
    .distinctUntilChanged()
    .collect 
        if (it is NotLoading) 
            // PagingDataAdapter.itemCount here
        
    

顺便说一句,null 是 Paging 中的一个特殊值,表示占位符,因此您不应提供包含 nulls 的 Paging 页面,这就是为什么 Value 泛型的下限为非空 @987654325 @而不是Any?

【讨论】:

感谢您的输入,但我不知道如何在 java 中实现它,这似乎是纯 kotlin,就像我在问题中提到的那样,我目前正在使用 java。是否可以提供与您给出的示例等效的 java? 在 Java 中,您可以使用 loadStateListener,或者如果您使用 rxjava,您可以将流转换为 rx 流。如果这是您首选的流式传输 API,也可以使用 toLiveData 助手 我无法理解如何按照您建议的方式关联 addLoadStateListener。此 Paging 3 非常令人困惑,并且缺少大量文档,这使得这变得更加难以理解。 我想我可能已经取得了一些进展,在这种情况下检查空虚是否正确? combinedLoadStates.getRefresh() instanceof LoadState.NotLoading &amp;&amp; myPagingDataAdapter.getItemCount() == 0我正在尝试根据您指向is NotLoading的原始答案来做这件事@ 是的,但是当任何 loadState 更改(包括 append 和 prepend)时,侦听器将触发,因此您只想过滤刷新中的更改。虽然如果你只是将视图的可见性设置为 GONE 冗余,它应该不会太糟糕【参考方案2】:

不幸的是,接受的答案不适用于我的情况。 因此,当 api 返回空列表(按设计不应该)时,我不会检查适配器的itemCount,而是抛出自定义异常(让我们称之为EmptyListException)。在我的PagingSource.load() 方法中,我检查获取的数据是否为空:

return if (pagedResponse.page.isEmpty())
    LoadResult.Error(EmptyListException())
 else 
    LoadResult.Page(pagedResponse.page, prevKey, nextKey)

然后我处理adapter.loadStateFlow中的结果。

【讨论】:

以上是关于如何检查 Paging 3 库中的列表大小或空列表的主要内容,如果未能解决你的问题,请参考以下文章

在使用 Paging library 3.0 时,我们如何将整个对象列表传递给 PagingDataAdapter?

Android Paging 3 - 从 Jetpack Compose 中的 PagingData<T> 对象获取数据列表

单击 Paging 3 库中的项目加载更多数据

仅具有本地 Room 数据库的 Android Paging v3:如何滚动到分页列表中的特定位置?

Jetpeck paging3实践——无限加载网页列表数据

Android Paging 3 - 从 PagingData<T> 对象获取数据列表