# AsyncPagingDataDiffer

Artifact: [androidx.paging:paging-runtime](https://developer.android.com/jetpack/androidx/releases/paging) [View Source](https://cs.android.com/search?q=file:androidx/paging/AsyncPagingDataDiffer.kt+class:androidx.paging.AsyncPagingDataDiffer) Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

*** ** * ** ***

Kotlin \|[Java](https://developer.android.com/reference/androidx/paging/AsyncPagingDataDiffer "View this page in Java") Common/AllAndroid/JVMNative/C/iOSJavaScript
- android

  ```
  class AsyncPagingDataDiffer<T : Any>
  ```

*** ** * ** ***

Helper class for mapping a `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` into a `https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView.Adapter`.

For simplicity, `https://developer.android.com/reference/kotlin/androidx/paging/PagingDataAdapter` can often be used in place of this class. `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer` is exposed for complex cases, and where overriding `https://developer.android.com/reference/kotlin/androidx/paging/PagingDataAdapter` to support paging isn't convenient.

## Summary

| ### Public constructors |
|---|---|
| `<T : https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html> https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#AsyncPagingDataDiffer(androidx.recyclerview.widget.DiffUtil.ItemCallback,androidx.recyclerview.widget.ListUpdateCallback,kotlin.coroutines.CoroutineContext,kotlin.coroutines.CoroutineContext)( diffCallback: https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/DiffUtil.ItemCallback<T>, updateCallback: https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/ListUpdateCallback, mainDispatcher: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines/-coroutine-context/index.html, workerDispatcher: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines/-coroutine-context/index.html )` | android |

| ### Public functions |
|---|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#addLoadStateListener(kotlin.Function1)(listener: (https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)` Add a `https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates` listener to observe the loading state of the current `https://developer.android.com/reference/kotlin/androidx/paging/PagingData`. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#addOnPagesUpdatedListener(kotlin.Function0)(listener: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)` Add a listener which triggers after the pages presented to the UI are updated, even if the actual items presented don't change. | android |
| `T?` | `@https://developer.android.com/reference/kotlin/androidx/annotation/MainThread https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#getItem(kotlin.Int)(index: @https://developer.android.com/reference/kotlin/androidx/annotation/IntRange(from = 0) https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html)` Get the item from the current PagedList at the specified index. | android |
| `T?` | `@https://developer.android.com/reference/kotlin/androidx/annotation/MainThread https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#peek(kotlin.Int)(index: @https://developer.android.com/reference/kotlin/androidx/annotation/IntRange(from = 0) https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html)` Returns the presented item at the specified position, without notifying Paging of the item access that would normally trigger page loads. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#refresh()()` Refresh the data presented by this `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer`. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#removeLoadStateListener(kotlin.Function1)(listener: (https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)` Remove a previously registered `https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates` listener. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#removeOnPagesUpdatedListener(kotlin.Function0)(listener: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)` Remove a previously registered listener for new `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` generations completing initial load and presenting to the UI. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#retry()()` Retry any failed load requests that would result in a `https://developer.android.com/reference/kotlin/androidx/paging/LoadState.Error` update to this `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer`. | android |
| `https://developer.android.com/reference/kotlin/androidx/paging/ItemSnapshotList<T>` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#snapshot()()` Returns a new `https://developer.android.com/reference/kotlin/androidx/paging/ItemSnapshotList` representing the currently presented items, including any placeholders if they are enabled. | android |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.paging.PagingData)(pagingData: https://developer.android.com/reference/kotlin/androidx/paging/PagingData<T>)` Present a `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` until it is invalidated by a call to `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#refresh()` or `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource#invalidate()`. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.lifecycle.Lifecycle,androidx.paging.PagingData)(lifecycle: https://developer.android.com/reference/kotlin/androidx/lifecycle/Lifecycle, pagingData: https://developer.android.com/reference/kotlin/androidx/paging/PagingData<T>)` Present a `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` until it is either invalidated or another call to `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.lifecycle.Lifecycle,androidx.paging.PagingData)` is made. | android |

| ### Public properties |
|---|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#itemCount()` Get the number of items currently presented by this Differ. | android |
| `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html<https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates>` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#loadStateFlow()` A hot `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html` of `https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates` that emits a snapshot whenever the loading state of the current `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` changes. | android |
| `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html<https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html>` | `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#onPagesUpdatedFlow()` A hot `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html` that emits after the pages presented to the UI are updated, even if the actual items presented don't change. | android |

## Public constructors

### AsyncPagingDataDiffer

android

```
<T : Any> AsyncPagingDataDiffer(
    diffCallback: DiffUtil.ItemCallback<T>,
    updateCallback: ListUpdateCallback,
    mainDispatcher: CoroutineContext = Dispatchers.Main,
    workerDispatcher: CoroutineContext = Dispatchers.Default
)
```

## Public functions

### addLoadStateListener

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
fun addLoadStateListener(listener: (CombinedLoadStates) -> Unit): Unit
```

Add a `https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates` listener to observe the loading state of the current `https://developer.android.com/reference/kotlin/androidx/paging/PagingData`.

As new `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` generations are submitted and displayed, the listener will be notified to reflect the current `https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates`.

```kotlin
import androidx.paging.LoadState

val adapter = UserPagingAdapter()
adapter.addLoadStateListener {
    // show a retry button outside the list when refresh hits an error
    retryButton.isVisible = it.refresh is LoadState.Error

    // swipeRefreshLayout displays whether refresh is occurring
    swipeRefreshLayout.isRefreshing = it.refresh is LoadState.Loading

    // show an empty state over the list when loading initially, before items are loaded
    emptyState.isVisible = it.refresh is LoadState.Loading && adapter.itemCount == 0
}
```

| Parameters |
|---|---|
| `listener: (https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/paging/LoadStates` listener to receive updates. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#removeLoadStateListener(kotlin.Function1)` |   |

### addOnPagesUpdatedListener

android Added in [3.1.0](https://developer.android.com/jetpack/androidx/releases/paging#3.1.0)

```
fun addOnPagesUpdatedListener(listener: () -> Unit): Unit
```

Add a listener which triggers after the pages presented to the UI are updated, even if the actual items presented don't change.

An update is triggered from one of the following:

- `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.paging.PagingData)` is called and initial load completes, regardless of any differences in the loaded data

- A `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource.LoadResult.Page` is inserted

- A `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource.LoadResult.Page` is dropped

| Parameters |
|---|---|
| `listener: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | called after pages presented are updated. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#removeOnPagesUpdatedListener(kotlin.Function0)` |   |

### getItem

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
@MainThread
fun getItem(index: @IntRange(from = 0) Int): T?
```

Get the item from the current PagedList at the specified index.

Note that this operates on both loaded items and null padding within the PagedList.

| Parameters |
|---|---|
| `index: @https://developer.android.com/reference/kotlin/androidx/annotation/IntRange(from = 0) https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | Index of item to get, must be \>= 0, and \<`https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#itemCount()` |

| Returns |
|---|---|
| `T?` | The item, or `null`, if a `null` placeholder is at the specified position. |

### peek

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
@MainThread
fun peek(index: @IntRange(from = 0) Int): T?
```

Returns the presented item at the specified position, without notifying Paging of the item access that would normally trigger page loads.

| Parameters |
|---|---|
| `index: @https://developer.android.com/reference/kotlin/androidx/annotation/IntRange(from = 0) https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | Index of the presented item to return, including placeholders. |

| Returns |
|---|---|
| `T?` | The presented item at position `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#peek(kotlin.Int)`, `null` if it is a placeholder |

### refresh

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
fun refresh(): Unit
```

Refresh the data presented by this `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer`.

`https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#refresh()` triggers the creation of a new `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` with a new instance of `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource` to represent an updated snapshot of the backing dataset. If a `https://developer.android.com/reference/kotlin/androidx/paging/RemoteMediator` is set, calling `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#refresh()` will also trigger a call to `https://developer.android.com/reference/kotlin/androidx/paging/RemoteMediator#load(androidx.paging.LoadType,androidx.paging.PagingState)` with `https://developer.android.com/reference/kotlin/androidx/paging/LoadType#REFRESH` to allow `https://developer.android.com/reference/kotlin/androidx/paging/RemoteMediator` to check for updates to the dataset backing `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource`.

Note: This API is intended for UI-driven refresh signals, such as swipe-to-refresh. Invalidation due repository-layer signals, such as DB-updates, should instead use `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource#invalidate()`.

```kotlin
import androidx.appcompat.app.AppCompatActivity
import androidx.paging.LoadState

class MyActivity : AppCompatActivity() {
    private lateinit var binding: MyActivityBinding
    private val pagingAdapter = UserPagingAdapter()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = MyActivityBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.recyclerView.adapter = pagingAdapter
        pagingAdapter.addLoadStateListener { loadStates ->
            binding.swipeRefreshLayout.isRefreshing = loadStates.refresh is LoadState.Loading
        }

        binding.swipeRefreshLayout.setOnRefreshListener { pagingAdapter.refresh() }
    }
}
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource#invalidate()` |   |

### removeLoadStateListener

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
fun removeLoadStateListener(listener: (CombinedLoadStates) -> Unit): Unit
```

Remove a previously registered `https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates` listener.

| Parameters |
|---|---|
| `listener: (https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | Previously registered listener. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#addLoadStateListener(kotlin.Function1)` |   |

### removeOnPagesUpdatedListener

android Added in [3.1.0](https://developer.android.com/jetpack/androidx/releases/paging#3.1.0)

```
fun removeOnPagesUpdatedListener(listener: () -> Unit): Unit
```

Remove a previously registered listener for new `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` generations completing initial load and presenting to the UI.

| Parameters |
|---|---|
| `listener: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | Previously registered listener. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#addOnPagesUpdatedListener(kotlin.Function0)` |   |

### retry

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
fun retry(): Unit
```

Retry any failed load requests that would result in a `https://developer.android.com/reference/kotlin/androidx/paging/LoadState.Error` update to this `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer`.

Unlike `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#refresh()`, this does not invalidate `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource`, it only retries failed loads within the same generation of `https://developer.android.com/reference/kotlin/androidx/paging/PagingData`.

`https://developer.android.com/reference/kotlin/androidx/paging/LoadState.Error` can be generated from two types of load requests:

- `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource#load(androidx.paging.PagingSource.LoadParams)` returning `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource.LoadResult.Error`

- `https://developer.android.com/reference/kotlin/androidx/paging/RemoteMediator#load(androidx.paging.LoadType,androidx.paging.PagingState)` returning `https://developer.android.com/reference/kotlin/androidx/paging/RemoteMediator.MediatorResult.Error`

### snapshot

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
fun snapshot(): ItemSnapshotList<T>
```

Returns a new `https://developer.android.com/reference/kotlin/androidx/paging/ItemSnapshotList` representing the currently presented items, including any placeholders if they are enabled.

### submitData

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
suspend fun submitData(pagingData: PagingData<T>): Unit
```

Present a `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` until it is invalidated by a call to `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#refresh()` or `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource#invalidate()`.

This method is typically used when collecting from a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html` produced by `https://developer.android.com/reference/kotlin/androidx/paging/Pager`. For RxJava or LiveData support, use the non-suspending overload of `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.paging.PagingData)`, which accepts a `https://developer.android.com/reference/kotlin/androidx/lifecycle/Lifecycle`.

Note: This method suspends while it is actively presenting page loads from a `https://developer.android.com/reference/kotlin/androidx/paging/PagingData`, until the `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` is invalidated. Although cancellation will propagate to this call automatically, collecting from a `https://developer.android.com/reference/kotlin/androidx/paging/Pager#flow()` with the intention of presenting the most up-to-date representation of your backing dataset should typically be done using `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/index.html`.

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/paging/Pager` |   |

### submitData

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
fun submitData(lifecycle: Lifecycle, pagingData: PagingData<T>): Unit
```

Present a `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` until it is either invalidated or another call to `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.lifecycle.Lifecycle,androidx.paging.PagingData)` is made.

This method is typically used when observing a RxJava or LiveData stream produced by `https://developer.android.com/reference/kotlin/androidx/paging/Pager`. For `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html` support, use the suspending overload of `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.lifecycle.Lifecycle,androidx.paging.PagingData)`, which automates cancellation via `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html` instead of relying of `https://developer.android.com/reference/kotlin/androidx/lifecycle/Lifecycle`.

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.lifecycle.Lifecycle,androidx.paging.PagingData)` |   |
| `https://developer.android.com/reference/kotlin/androidx/paging/Pager` |   |

## Public properties

### itemCount

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
val itemCount: Int
```

Get the number of items currently presented by this Differ. This value can be directly returned to `https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView.Adapter#getItemCount()`.

| Returns |
|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | Number of items being presented, including placeholders. |

### loadStateFlow

android Added in [3.0.0](https://developer.android.com/jetpack/androidx/releases/paging#3.0.0)

```
val loadStateFlow: Flow<CombinedLoadStates>
```

A hot `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html` of `https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates` that emits a snapshot whenever the loading state of the current `https://developer.android.com/reference/kotlin/androidx/paging/PagingData` changes.

This flow is conflated, so it buffers the last update to `https://developer.android.com/reference/kotlin/androidx/paging/CombinedLoadStates` and delivers the current load states on collection when RecyclerView is not dispatching layout.

```kotlin
import androidx.lifecycle.lifecycleScope
import androidx.paging.LoadState

val adapter = UserPagingAdapter()
lifecycleScope.launch {
    adapter.loadStateFlow
        .map { it.refresh }
        .distinctUntilChanged()
        .collectLatest {
            // show a retry button outside the list when refresh hits an error
            retryButton.isVisible = it is LoadState.Error

            // swipeRefreshLayout displays whether refresh is occurring
            swipeRefreshLayout.isRefreshing = it is LoadState.Loading

            // show an empty state over the list when loading initially, before items are loaded
            emptyState.isVisible = it is LoadState.Loading && adapter.itemCount == 0
        }
}
```

### onPagesUpdatedFlow

android Added in [3.1.0](https://developer.android.com/jetpack/androidx/releases/paging#3.1.0)

```
val onPagesUpdatedFlow: Flow<Unit>
```

A hot `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html` that emits after the pages presented to the UI are updated, even if the actual items presented don't change.

An update is triggered from one of the following:

- `https://developer.android.com/reference/kotlin/androidx/paging/AsyncPagingDataDiffer#submitData(androidx.paging.PagingData)` is called and initial load completes, regardless of any differences in the loaded data

- A `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource.LoadResult.Page` is inserted

- A `https://developer.android.com/reference/kotlin/androidx/paging/PagingSource.LoadResult.Page` is dropped

Note: This is a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-shared-flow/index.html` configured to replay 0 items with a buffer of size 64. If a collector lags behind page updates, it may trigger multiple times for each intermediate update that was presented while your collector was still working. To avoid this behavior, you can `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/index.html` this `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html` so that you only receive the latest update, which is useful in cases where you are simply updating UI and don't care about tracking the exact number of page updates.