Add .snapshot and .peek() APIs to PagingDataAdapter

Updating leanback-paging to latest stable version of Paging.

This CL reverts the unreleased beta version bump to allow another alpha
version to push the new presenter APIs, .peek() and .snapshot(),
matching the API surface of other presenter APIs on paging.

Relnote: "Added .peek() and .snapshot() APIs to PagingDataAdapter,
  allowing inspection of presented data without triggering page fetch."
Test: ./gradlew leanback:leanback-paging:cC
Change-Id: Ic89171a55a10a73b585f130d2a9eb1b8927db1fd
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index fe922a5..41aa54f 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -76,7 +76,7 @@
     val INTERPOLATOR = Version("1.1.0-alpha01")
     val JETIFIER = Version("1.0.0-beta11")
     val LEANBACK = Version("1.2.0-alpha01")
-    val LEANBACK_PAGING = Version("1.1.0-beta01")
+    val LEANBACK_PAGING = Version("1.1.0-alpha08")
     val LEANBACK_PREFERENCE = Version("1.2.0-alpha01")
     val LEANBACK_TAB = Version("1.1.0-beta01")
     val LEGACY = Version("1.1.0-alpha01")
diff --git a/leanback/leanback-paging/api/1.1.0-beta01.txt b/leanback/leanback-paging/api/1.1.0-beta01.txt
deleted file mode 100644
index 7cdea77..0000000
--- a/leanback/leanback-paging/api/1.1.0-beta01.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-// Signature format: 4.0
-package androidx.leanback.paging {
-
-  public final class PagingDataAdapter<T> extends androidx.leanback.widget.ObjectAdapter {
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
-    method public T? get(int position);
-    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
-    method public void refresh();
-    method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
-    method public void retry();
-    method public int size();
-    method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
-    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
-  }
-
-}
-
diff --git a/leanback/leanback-paging/api/current.txt b/leanback/leanback-paging/api/current.txt
index 7cdea77..897a34a 100644
--- a/leanback/leanback-paging/api/current.txt
+++ b/leanback/leanback-paging/api/current.txt
@@ -14,10 +14,12 @@
     method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
     method public T? get(int position);
     method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+    method public T? peek(@IntRange(from=0) int index);
     method public void refresh();
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
     method public void retry();
     method public int size();
+    method public androidx.paging.ItemSnapshotList<T> snapshot();
     method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
diff --git a/leanback/leanback-paging/api/public_plus_experimental_1.1.0-beta01.txt b/leanback/leanback-paging/api/public_plus_experimental_1.1.0-beta01.txt
deleted file mode 100644
index 7cdea77..0000000
--- a/leanback/leanback-paging/api/public_plus_experimental_1.1.0-beta01.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-// Signature format: 4.0
-package androidx.leanback.paging {
-
-  public final class PagingDataAdapter<T> extends androidx.leanback.widget.ObjectAdapter {
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
-    method public T? get(int position);
-    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
-    method public void refresh();
-    method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
-    method public void retry();
-    method public int size();
-    method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
-    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
-  }
-
-}
-
diff --git a/leanback/leanback-paging/api/public_plus_experimental_current.txt b/leanback/leanback-paging/api/public_plus_experimental_current.txt
index 7cdea77..897a34a 100644
--- a/leanback/leanback-paging/api/public_plus_experimental_current.txt
+++ b/leanback/leanback-paging/api/public_plus_experimental_current.txt
@@ -14,10 +14,12 @@
     method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
     method public T? get(int position);
     method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+    method public T? peek(@IntRange(from=0) int index);
     method public void refresh();
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
     method public void retry();
     method public int size();
+    method public androidx.paging.ItemSnapshotList<T> snapshot();
     method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
diff --git a/leanback/leanback-paging/api/res-1.1.0-beta01.txt b/leanback/leanback-paging/api/res-1.1.0-beta01.txt
deleted file mode 100644
index e69de29..0000000
--- a/leanback/leanback-paging/api/res-1.1.0-beta01.txt
+++ /dev/null
diff --git a/leanback/leanback-paging/api/restricted_1.1.0-beta01.txt b/leanback/leanback-paging/api/restricted_1.1.0-beta01.txt
deleted file mode 100644
index 7cdea77..0000000
--- a/leanback/leanback-paging/api/restricted_1.1.0-beta01.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-// Signature format: 4.0
-package androidx.leanback.paging {
-
-  public final class PagingDataAdapter<T> extends androidx.leanback.widget.ObjectAdapter {
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.Presenter presenter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher, optional kotlinx.coroutines.CoroutineDispatcher workerDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback, optional kotlinx.coroutines.CoroutineDispatcher mainDispatcher);
-    ctor public PagingDataAdapter(androidx.leanback.widget.PresenterSelector presenterSelector, androidx.recyclerview.widget.DiffUtil.ItemCallback<T> diffCallback);
-    method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
-    method public T? get(int position);
-    method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
-    method public void refresh();
-    method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
-    method public void retry();
-    method public int size();
-    method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
-    method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
-    property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
-  }
-
-}
-
diff --git a/leanback/leanback-paging/api/restricted_current.txt b/leanback/leanback-paging/api/restricted_current.txt
index 7cdea77..897a34a 100644
--- a/leanback/leanback-paging/api/restricted_current.txt
+++ b/leanback/leanback-paging/api/restricted_current.txt
@@ -14,10 +14,12 @@
     method public void addLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
     method public T? get(int position);
     method public kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> getLoadStateFlow();
+    method public T? peek(@IntRange(from=0) int index);
     method public void refresh();
     method public void removeLoadStateListener(kotlin.jvm.functions.Function1<? super androidx.paging.CombinedLoadStates,kotlin.Unit> listener);
     method public void retry();
     method public int size();
+    method public androidx.paging.ItemSnapshotList<T> snapshot();
     method public suspend Object? submitData(androidx.paging.PagingData<T> pagingData, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     method public void submitData(androidx.lifecycle.Lifecycle lifecycle, androidx.paging.PagingData<T> pagingData);
     property public final kotlinx.coroutines.flow.Flow<androidx.paging.CombinedLoadStates> loadStateFlow;
diff --git a/leanback/leanback-paging/build.gradle b/leanback/leanback-paging/build.gradle
index 3585e40..4bd6b00 100644
--- a/leanback/leanback-paging/build.gradle
+++ b/leanback/leanback-paging/build.gradle
@@ -12,7 +12,7 @@
 dependencies {
     api("androidx.annotation:annotation:1.1.0")
     api("androidx.leanback:leanback:1.1.0-beta01")
-    api("androidx.paging:paging-runtime:3.0.0-beta03")
+    api("androidx.paging:paging-runtime:3.0.0")
 
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.testCore)
diff --git a/leanback/leanback-paging/src/androidTest/java/androidx/leanback/paging/PagingDataAdapterTest.kt b/leanback/leanback-paging/src/androidTest/java/androidx/leanback/paging/PagingDataAdapterTest.kt
index 7e4b192..5d4f5c6 100644
--- a/leanback/leanback-paging/src/androidTest/java/androidx/leanback/paging/PagingDataAdapterTest.kt
+++ b/leanback/leanback-paging/src/androidTest/java/androidx/leanback/paging/PagingDataAdapterTest.kt
@@ -17,7 +17,6 @@
 
 import androidx.lifecycle.testing.TestLifecycleOwner
 import androidx.paging.CombinedLoadStates
-import androidx.paging.ExperimentalPagingApi
 import androidx.paging.LoadState
 import androidx.paging.Pager
 import androidx.paging.PagingConfig
@@ -33,6 +32,7 @@
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.TestCoroutineScope
 import kotlinx.coroutines.test.runBlockingTest
@@ -42,7 +42,7 @@
 import kotlin.coroutines.ContinuationInterceptor
 import kotlin.test.assertEquals
 
-@OptIn(ExperimentalCoroutinesApi::class, ExperimentalPagingApi::class)
+@OptIn(ExperimentalCoroutinesApi::class)
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class PagingDataAdapterTest {
@@ -62,15 +62,7 @@
         val pagingSource = TestPagingSource()
         val pagingDataAdapter =
             PagingDataAdapter(
-                diffCallback = object : DiffUtil.ItemCallback<Int>() {
-                    override fun areContentsTheSame(oldItem: Int, newItem: Int): Boolean {
-                        return oldItem == newItem
-                    }
-
-                    override fun areItemsTheSame(oldItem: Int, newItem: Int): Boolean {
-                        return oldItem == newItem
-                    }
-                },
+                diffCallback = DiffCallback,
                 workerDispatcher = Dispatchers.Main
             )
         val pager = Pager(
@@ -103,15 +95,7 @@
     fun testLoadStateListenerCallbacks() = testScope.runBlockingTest {
         val pagingDataAdapter =
             PagingDataAdapter(
-                diffCallback = object : DiffUtil.ItemCallback<Int>() {
-                    override fun areContentsTheSame(oldItem: Int, newItem: Int): Boolean {
-                        return oldItem == newItem
-                    }
-
-                    override fun areItemsTheSame(oldItem: Int, newItem: Int): Boolean {
-                        return oldItem == newItem
-                    }
-                },
+                diffCallback = DiffCallback,
                 workerDispatcher = Dispatchers.Main
             )
         val loadEvents = mutableListOf<CombinedLoadStates>()
@@ -163,4 +147,83 @@
             actual = loadEvents
         )
     }
+
+    @Test
+    fun snapshot() = testScope.runBlockingTest {
+        val pagingSource = TestPagingSource()
+        val pagingDataAdapter =
+            PagingDataAdapter(
+                diffCallback = DiffCallback,
+                workerDispatcher = Dispatchers.Main
+            )
+        val pager = Pager(
+            config = PagingConfig(
+                pageSize = 2,
+                prefetchDistance = 1,
+                enablePlaceholders = true,
+                initialLoadSize = 2
+            ),
+            initialKey = 50
+        ) {
+            pagingSource
+        }
+        val job = launch {
+            pager.flow.collectLatest {
+                pagingDataAdapter.submitData(it)
+            }
+        }
+
+        assertEquals(listOf(), pagingDataAdapter.snapshot())
+
+        advanceUntilIdle()
+        assertEquals(
+            List(50) { null } + listOf(50, 51) + List(48) { null },
+            pagingDataAdapter.snapshot()
+        )
+
+        job.cancel()
+    }
+
+    @Test
+    fun peek() = testScope.runBlockingTest {
+        val pagingSource = TestPagingSource()
+        val pagingDataAdapter =
+            PagingDataAdapter(
+                diffCallback = DiffCallback,
+                workerDispatcher = Dispatchers.Main
+            )
+        val pager = Pager(
+            config = PagingConfig(
+                pageSize = 2,
+                prefetchDistance = 1,
+                enablePlaceholders = true,
+                initialLoadSize = 2
+            ),
+            initialKey = 50
+        ) {
+            pagingSource
+        }
+        val job = launch {
+            pager.flow.collectLatest {
+                pagingDataAdapter.submitData(it)
+            }
+        }
+
+        advanceUntilIdle()
+        assertEquals(null, pagingDataAdapter.peek(0))
+        assertEquals(50, pagingDataAdapter.peek(50))
+        assertEquals(null, pagingDataAdapter.peek(99))
+
+        job.cancel()
+    }
 }
+
+private object DiffCallback : DiffUtil.ItemCallback<Int>() {
+    override fun areContentsTheSame(oldItem: Int, newItem: Int): Boolean {
+        return oldItem == newItem
+    }
+
+    override fun areItemsTheSame(oldItem: Int, newItem: Int): Boolean {
+        return oldItem == newItem
+    }
+}
\ No newline at end of file
diff --git a/leanback/leanback-paging/src/main/java/androidx/leanback/paging/PagingDataAdapter.kt b/leanback/leanback-paging/src/main/java/androidx/leanback/paging/PagingDataAdapter.kt
index b40f6b5..86e2d6a 100644
--- a/leanback/leanback-paging/src/main/java/androidx/leanback/paging/PagingDataAdapter.kt
+++ b/leanback/leanback-paging/src/main/java/androidx/leanback/paging/PagingDataAdapter.kt
@@ -16,12 +16,14 @@
 
 package androidx.leanback.paging
 
+import androidx.annotation.IntRange
 import androidx.leanback.widget.ObjectAdapter
 import androidx.leanback.widget.Presenter
 import androidx.leanback.widget.PresenterSelector
 import androidx.lifecycle.Lifecycle
 import androidx.paging.AsyncPagingDataDiffer
 import androidx.paging.CombinedLoadStates
+import androidx.paging.ItemSnapshotList
 import androidx.paging.LoadState
 import androidx.paging.LoadType
 import androidx.paging.Pager
@@ -32,7 +34,6 @@
 import androidx.recyclerview.widget.ListUpdateCallback
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.FlowPreview
 import kotlinx.coroutines.flow.Flow
 
 /**
@@ -149,10 +150,6 @@
      * Present a [PagingData] until it is invalidated by a call to [refresh] or
      * [PagingSource.invalidate].
      *
-     * [submitData] should be called on the same [CoroutineDispatcher] where updates will be
-     * dispatched to UI, typically [Dispatchers.Main] (this is done for you if you use
-     * `lifecycleScope.launch {}`).
-     *
      * This method is typically used when collecting from a [Flow] produced by [Pager]. For RxJava
      * or LiveData support, use the non-suspending overload of [submitData], which accepts a
      * [Lifecycle].
@@ -217,13 +214,27 @@
     }
 
     /**
+     * Returns the presented item at the specified position, without notifying Paging of the item
+     * access that would normally trigger page loads.
+     *
+     * @param index Index of the presented item to return, including placeholders.
+     * @return The presented item at position [index], `null` if it is a placeholder.
+     */
+    fun peek(@IntRange(from = 0) index: Int) = differ.peek(index)
+
+    /**
+     * Returns a new [ItemSnapshotList] representing the currently presented items, including any
+     * placeholders if they are enabled.
+     */
+    fun snapshot(): ItemSnapshotList<T> = differ.snapshot()
+
+    /**
      * A hot [Flow] of [CombinedLoadStates] that emits a snapshot whenever the loading state of the
      * current [PagingData] changes.
      *
      * This flow is conflated, so it buffers the last update to [CombinedLoadStates] and
      * immediately delivers the current load states on collection.
      */
-    @OptIn(FlowPreview::class)
     val loadStateFlow: Flow<CombinedLoadStates>
         get() = differ.loadStateFlow