{% setvar book_path %}/reference/kotlin/androidx/_book.yaml{% endsetvar %} {% include "_shared/_reference-head-tags.html" %}
abstract class PagingSource<Key : Any, Value : Any>
ListenableFuturePagingSource |
ListenableFuture-based compatibility wrapper around |
RxPagingSource |
Rx-based compatibility wrapper around |
RxPagingSource |
Rx-based compatibility wrapper around |
Base class for an abstraction of pageable static data from some source, where loading pages of data is typically an expensive operation. Some examples of common PagingSource
s might be from network or from a database.
An instance of a PagingSource
is used to load pages of data for an instance of PagingData
.
A PagingData
can grow as it loads more data, but the data loaded cannot be updated. If the underlying data set is modified, a new PagingSource
/ PagingData
pair must be created to represent an updated snapshot of the data.
PagingData
queries data from its PagingSource
in response to loading hints generated as the user scrolls in a RecyclerView
.
To control how and when a PagingData
queries data from its PagingSource
, see PagingConfig
, which defines behavior such as PagingConfig.pageSize
and PagingConfig.prefetchDistance
.
A PagingSource
/ PagingData
pair is a snapshot of the data set. A new PagingData
/ PagingData
must be created if an update occurs, such as a reorder, insert, delete, or content update occurs. A PagingSource
must detect that it cannot continue loading its snapshot (for instance, when Database query notices a table being invalidated), and call invalidate
. Then a new PagingSource
/ PagingData
pair would be created to represent data from the new state of the database query.
To present data loaded by a PagingSource
to a RecyclerView
, create an instance of Pager
, which provides a stream of PagingData
that you may collect from and submit to a PagingDataAdapter
.
/** * Sample page-keyed PagingSource, which uses Int page number to load pages. * * Loads Items from network requests via Retrofit to a backend service. * * Note that the key type is Int, since we're using page number to load a page. */ class MyPagingSource( val myBackend: MyBackendService ) : PagingSource<Int, Item>() { override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Item> { // Retrofit calls that return the body type throw either IOException for network // failures, or HttpException for any non-2xx HTTP status codes. This code reports all // errors to the UI, but you can inspect/wrap the exceptions to provide more context. return try { // Key may be null during a refresh, if no explicit key is passed into Pager // construction. Use 0 as default, because our API is indexed started at index 0 val pageNumber = params.key ?: 0 // Suspending network load via Retrofit. This doesn't need to be wrapped in a // withContext(Dispatcher.IO) { ... } block since Retrofit's Coroutine // CallAdapter dispatches on a worker thread. val response = myBackend.searchItems(pageNumber) // Since 0 is the lowest page number, return null to signify no more pages should // be loaded before it. val prevKey = if (pageNumber > 0) pageNumber - 1 else null // This API defines that it's out of data when a page returns empty. When out of // data, we return `null` to signify no more pages should be loaded val nextKey = if (response.items.isNotEmpty()) pageNumber + 1 else null LoadResult.Page( data = response.items, prevKey = prevKey, nextKey = nextKey ) } catch (e: IOException) { LoadResult.Error(e) } catch (e: HttpException) { LoadResult.Error(e) } } override fun getRefreshKey(state: PagingState<Int, Item>): Int? { return state.anchorPosition?.let { state.closestPageToPosition(it)?.prevKey?.plus(1) ?: state.closestPageToPosition(it)?.nextKey?.minus(1) } } }
/** * Sample item-keyed [PagingSource], which uses String tokens to load pages. * * Loads Items from network requests via Retrofit to a backend service. */ class MyPagingSource( val myBackend: MyBackendService ) : PagingSource<String, Item>() { override suspend fun load(params: LoadParams<String>): LoadResult<String, Item> { // Retrofit calls that return the body type throw either IOException for network // failures, or HttpException for any non-2xx HTTP status codes. This code reports all // errors to the UI, but you can inspect/wrap the exceptions to provide more context. return try { // Suspending network load via Retrofit. This doesn't need to be wrapped in a // withContext(Dispatcher.IO) { ... } block since Retrofit's Coroutine // CallAdapter dispatches on a worker thread. val response = myBackend.searchItems(params.key) LoadResult.Page( data = response.items, prevKey = response.prev, nextKey = response.next ) } catch (e: IOException) { LoadResult.Error(e) } catch (e: HttpException) { LoadResult.Error(e) } } override fun getRefreshKey(state: PagingState<String, Item>): String? { return state.anchorPosition?.let { state.closestItemToPosition(it)?.id } } }
Parameters | |
---|---|
<Key : Any> |
Type of key which define what data to load. E.g. |
<Value : Any> |
Type of data loaded in by this |
See also | |
---|---|
Pager |
Nested types |
|
---|---|
PagingSource.LoadParams |
Params for a load request on a |
PagingSource.LoadParams.Append |
Params to load a page of data from a |
PagingSource.LoadParams.Prepend |
Params to load a page of data from a |
PagingSource.LoadParams.Refresh |
Params for an initial load request on a |
PagingSource.LoadResult |
Result of a load request from |
PagingSource.LoadResult.Error |
Error result object for |
PagingSource.LoadResult.Page |
Success result object for |
PagingSource.LoadResult.Page.Companion |
Public properties |
|
---|---|
Boolean |
Whether this |
open Boolean |
|
open Boolean |
|
Public constructors |
|
---|---|
<Key : Any, Value : Any> PagingSource() |
Public functions |
|
---|---|
abstract Key? |
getRefreshKey(state: PagingState<Key, Value>) Provide a |
Unit |
Signal the |
abstract suspend PagingSource.LoadResult<Key, Value> |
load(params: PagingSource.LoadParams<Key>) Loading API for |
Unit |
registerInvalidatedCallback(onInvalidatedCallback: () -> Unit) Add a callback to invoke when the |
Unit |
unregisterInvalidatedCallback(onInvalidatedCallback: () -> Unit) Remove a previously added invalidate callback. |
val invalid: Boolean
Whether this PagingSource
has been invalidated, which should happen when the data this PagingSource
represents changes since it was first instantiated.
open val jumpingSupported: Boolean
true
if this PagingSource
supports jumping, false
otherwise.
Override this to true
if pseudo-fast scrolling via jumps is supported.
A jump occurs when a RecyclerView
scrolls through a number of placeholders defined by PagingConfig.jumpThreshold
and triggers a load with LoadType
.
PagingSource
s that support jumps should override getRefreshKey
to return a Key
that would load data fulfilling the viewport given a user's current PagingState.anchorPosition
.
See also | |
---|---|
jumpThreshold |
open val keyReuseSupported: Boolean
true
if this PagingSource
expects to re-use keys to load distinct pages without a call to invalidate
, false
otherwise.
<Key : Any, Value : Any> PagingSource()
Parameters | |
---|---|
<Key : Any> |
Type of key which define what data to load. E.g. |
<Value : Any> |
Type of data loaded in by this |
abstract fun getRefreshKey(state: PagingState<Key, Value>): Key?
Provide a Key
used for the initial load
for the next PagingSource
due to invalidation of this PagingSource
. The Key
is provided to load
via LoadParams.key
.
The Key
returned by this method should cause load
to load enough items to fill the viewport around the last accessed position, allowing the next generation to transparently animate in. The last accessed position can be retrieved via state.anchorPosition
, which is typically the top-most or bottom-most item in the viewport due to access being triggered by binding items as they scroll into view.
For example, if items are loaded based on integer position keys, you can return state.anchorPosition
.
Alternately, if items contain a key used to load, get the key from the item in the page at index state.anchorPosition
.
Parameters | |
---|---|
state: PagingState<Key, Value> |
|
fun invalidate(): Unit
Signal the PagingSource
to stop loading.
This method is idempotent. i.e., If invalidate
has already been called, subsequent calls to this method should have no effect.
abstract suspend fun load(params: PagingSource.LoadParams<Key>): PagingSource.LoadResult<Key, Value>
Loading API for PagingSource
.
Implement this method to trigger your async load (e.g. from database or network).
fun registerInvalidatedCallback(onInvalidatedCallback: () -> Unit): Unit
Add a callback to invoke when the PagingSource
is first invalidated.
Once invalidated, a PagingSource
will not become valid again.
A PagingSource
will only invoke its callbacks once - the first time invalidate
is called, on that thread.
Parameters | |
---|---|
onInvalidatedCallback: () -> Unit |
The callback that will be invoked on thread that invalidates the |
fun unregisterInvalidatedCallback(onInvalidatedCallback: () -> Unit): Unit
Remove a previously added invalidate callback.
Parameters | |
---|---|
onInvalidatedCallback: () -> Unit |
The previously added callback. |