Android Paging 3 中如何区分初始加载和内容变化?

问题描述 投票:0回答:1

我有一个 RecyclerView,它使用 PagingDataAdapter 来显示其项目。在整个页面的初始加载时,我想显示一个 Shimmer 加载占位符。但是,当我尝试执行此操作时,加载占位符也会显示单个项目的少量内容更改。这使得整个屏幕闪烁,因为它在加载期间隐藏了 RecyclerView,并在加载内容更改后重新显示它。我不希望在单个内容更改时显示加载占位符。

我正在检查适配器的加载状态侦听器中的加载状态:

addLoadStateListener {
    val taskListState = when (it.refresh) { // triggered for both initial load and content change
        is LoadState.Loading -> ScheduleViewModel.TaskListState.LOADING
        // I want something like if (loadStateIsForInitialLoad()) ScheduleViewModel.TaskListState.LOADING else ScheduleViewModel.TaskListState.PRESENT
        is LoadState.Error -> ScheduleViewModel.TaskListState.ERROR
        is LoadState.NotLoading ->
            if (it.append.endOfPaginationReached && itemCount < 1) {
                ScheduleViewModel.TaskListState.EMPTY
            } else {
                ScheduleViewModel.TaskListState.PRESENT
            }
    }
    scheduleViewModel.setTaskListState(taskListState)
}

内容更改通过数据库:

class ScheduleViewModel @Inject constructor(private val taskRepository: TaskRepository) :
        ViewModel() {

  fun updateDoneState(task: TaskItem) {
    viewModelScope.launch(Dispatchers.IO) {
        if (task.isDone) {
            taskRepository.markUndone(task.id)
        } else {
            taskRepository.markDone(task.id)
        }
    }
  }
}

布局:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable name="viewModel" type="ogbe.eva.prompt.ui.schedule.ScheduleViewModel"/>
    </data>
    <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        <com.facebook.shimmer.ShimmerFrameLayout
                android:id="@+id/shimmerFrameLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:isVisible="@{viewModel.isLoading}">

            <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                <include layout="@layout/item_task_placeholder"/>

                <include layout="@layout/item_task_placeholder"/>

                <include layout="@layout/item_task_placeholder"/>

                <include layout="@layout/item_task_placeholder"/>

                <include layout="@layout/item_task_placeholder"/>

            </LinearLayout>

        </com.facebook.shimmer.ShimmerFrameLayout>

        <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/task_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="@dimen/spacing_sm"
                app:isVisible="@{viewModel.isPresent}"/>

    </FrameLayout>
</layout>

看起来CombinedLoadStates对于初始加载和内容更改只有一种刷新加载状态。还有其他方法可以区分吗?

android android-recyclerview android-paging shimmer
1个回答
3
投票

您在使用

RemoteMediator
吗?如果是这样,您只需观察
CombinedLoadStates.mediator.refresh
的变化即可。
CombinedLoadStates.refresh
只是一个帮助器,它结合了“常见”用例的中介器 + 源状态。

如果您仅使用

PagingSource
并与
RemoteMediator
分开更新数据库/失效,您还可以检查
adapter.itemCount
以确定“初始负载”。

adapter.addLoadStateListener { loadStates ->
  when (loadStates.source.refresh) {
    is NotLoading -> {
      // Always redundantly disable loading spinner here, which assumes doing so
      // is stateless.
      scheduleViewModel.setTaskListState(
        if (it.append.endOfPaginationReached && itemCount < 1) {
          ScheduleViewModel.TaskListState.EMPTY
        } else {
          ScheduleViewModel.TaskListState.PRESENT
        }
      )
    }
    is LoadState.Loading -> {
      if (adapter.itemCount == 0) {
        ScheduleViewModel.TaskListState.LOADING
      } else {
        ScheduleViewModel.TaskListState.PRESENT
      }
    }
    is LoadState.Error -> ScheduleViewModel.TaskListState.ERROR
  }
}

否则,您也可以自己跟踪并与

loadStateFlow
混合,但需要更准确地定义初始负载的含义。例如,配置更改或进程死亡计数是否作为初始加载,还是您只关心非缓存(在内存和数据库中)的情况?

© www.soinside.com 2019 - 2024. All rights reserved.