Android Jetpack中Paging3 转换数据流

本文详细介绍了如何在Android Jetpack Paging3中对数据流进行转换,包括基本转换、数据过滤、添加列表分隔符,以及如何避免重复工作。通过使用map()操作,可以对数据进行过滤、模型转换和添加界面分隔符,从而提高列表的可读性和用户体验。同时,使用cachedIn()可以确保在配置更改时避免不必要的数据加载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


转换数据流

使用分页数据时,您通常需要在加载数据流时对其进行转换。例如,您可能需要过滤一系列数据项,或者将数据项转换为其他类型,才能在界面中呈现它们。数据流转换的另一个常见用例是添加列表分隔符。

概括来说,直接对数据流进行转换可让您将存储库构造和界面构造分开。

执行基本转换

由于 PagingData 封装在响应式数据流中,因此您可以在加载数据之后、呈现数据之前逐步对数据执行转换操作。

为了对数据流中的每个 PagingData 对象执行转换,请将转换操作放入对数据流的 map() 操作中:

Kotlin
Coroutines

pager.flow // Type is Flow<PagingData<User>>.
  // Map the outer stream so that the transformations are applied to
  // each new generation of PagingData.
  .map {
    pagingData ->
    // Transformations in this block are applied to the items
    // in the paged data.
}

Java
RxJava

PagingRx.getFlowable(pager) // Type is Flowable<PagingData<User>>.
  // Map the outer stream so that the transformations are applied to
  // each new generation of PagingData.
  .map(pagingData -> {
   
    // Transformations in this block are applied to the items
    // in the paged data.
  });

Java
Guava/LiveData

// Map the outer stream so that the transformations are applied to
// each new generation of PagingData.
Transformations.map(
  // Type is LiveData<PagingData<User>>.
  PagingLiveData.getLiveData(pager),
  pagingData -> {
   
    // Transformations in this block are applied to the items
    // in the paged data.
  });

转换数据

可对数据流进行的最基本操作就是将其转换为其他类型。获得对 PagingData 对象的访问权限后,您可以对 PagingData 对象的分页列表中的每个单项执行 map() 操作。

该操作的一个常见用例是将某个网络或数据库层对象映射到界面层中专用的某个对象。以下示例演示了如何执行此类映射操作:

Kotlin
Coroutines

pager.flow // Type is Flow<PagingData<User>>.
  .map {
    pagingData ->
    pagingData.map {
    user -> UiModel(user) }
  }

Java
RxJava

// Type is Flowable<PagingData<User>>.
PagingRx.getFlowable(pager)
  .map(pagingData ->
    pagingData.map(UiModel.UserModel::new)
  )

Java
Guava/LiveData

Transformations.map(
  // Type is LiveData<PagingData<User>>.
  PagingLiveData.getLiveData(pager),
  pagingData ->
    pagingData.map(UiModel.UserModel::new)
)

另一种常见的数据转换是获取用户输入(例如查询字符串),然后将其转换为要显示的请求输出。若要设置该数据转换,您需要监听并捕获用户查询输入、执行相应请求并将查询结果推送回界面。

您可以使用数据流 API 来监听查询输入。将数据流引用保留在 ViewModel 中。界面层不应直接访问该类;相反,应该定义一个函数来通知 ViewModel 相关用户查询。

Kotlin
Coroutines

private val queryFlow = MutableStateFlow("")

fun onQueryChanged(query: String) {
   
  queryFlow.value = query
}

Java
RxJava

private BehaviorSubject<String> querySubject = BehaviorSubject.create("");

public void onQueryChanged(String query) {
   
  queryFlow.onNext(query)
}

Java
Guava/LiveData

private MutableLiveData<String> queryLiveData = new MutableLiveData("");

public void onQueryChanged(String query) {
   
  queryFlow.setValue(query)
}

使用 flatMapLatest 或 switchMap 等操作可以确保只将最新结果返回到界面。如果用户在数据库操作结束前更改查询输入,这些操作会舍弃旧查询的结果,并立即启动新的搜索。

过滤数据

另一种常见操作是过滤。您可以根据用户条件来过滤数据;如果根据其他条件应该隐藏数据,您也可以从界面中移除相应数据。

您需要将这些过滤操作放入 map() 调用中,因为该过滤条件适用于 PagingData 对象。数据从 PagingData 中过滤掉后,系统会将新的 PagingData 实例传递到界面层进行显示。

Kotlin
Coroutines

pager.flow // Type is Flow<PagingData<User>>.
  .map {
    pagingData ->
    pagingData.filter {
    user -> !user.hiddenFromUi }
  }

Java
RxJava

// Type is Flowable<PagingData<User>>.
PagingRx.getFlowable(pager)
  .map(pagingData ->
    pagingData.filter(user -> !user.isHiddenFromUi())
  )
}

Java
Guava/LiveData

Transformations.map(
  // Type is LiveData<PagingData<User>>.
  PagingLiveData.getLiveData(pager),
  pagingData ->
    pagingData.filter(user -> !user.isHiddenFromUi())
)

添加列表分隔符

Paging 库支持动态列表分隔符。您可以通过将分隔符作为 RecyclerView 列表项直接插入到数据流中来提高列表的可读性。因此,分隔符是功能完备的 ViewHolder 对象,可支持互动、无障碍功能焦点以及 View 提供的所有其他功能。

将分隔符插入到分页列表中需要执行以下三个步骤:

  1. 转换界面模型,以适应分隔符项。
  2. 转换数据流,以便在加载数据之后、呈现数据之前动态添加分隔符。
  3. 更新界面,以处理分隔符项。

注意:如果您不需要列表分隔符支持互动或实现无障碍功能聚焦,则使用 RecyclerView.ItemDecoration 来创建静态列表分隔符会更简单。

转换界面模型

Paging 库将列表分隔符作为实际的列表项插入到 RecyclerView 中,但分隔符必须与列表中的数据项区分开来,以便其能够绑定到具有不同界面的其他 ViewHolder 类型。解决方案是创建一个具有表示数据和分隔符的子类的 Kotlin 密封类。或者,您也可以创建一个可由您的列表项类和分隔符类扩展的基类。

假设您想要向 User 项的分页列表添加分隔符。以下代码段展示了如何创建基类,其中的实例可以是 UserModel 或 SeparatorModel:

Kotlin
Coroutines

sealed class UiModel {
   
  class UserModel(val id: String, val label: String) : UiModel() {
   
    constructor(user: User) : this(user.id, user.label)
  }

  class SeparatorModel(val description: String) : UiModel()
}

Java
RxJava

class UiModel {
   
  pri
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yu-Knight

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值