gradle: upgrade dependencies and sync LazyPagingItems from upstream

This commit is contained in:
Harsh Shandilya 2021-12-15 00:16:32 +05:30
parent eeddc3a3e6
commit b5c2dc9aaf
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
5 changed files with 124 additions and 80 deletions

View file

@ -18,11 +18,9 @@ import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.paging.CombinedLoadStates
import androidx.paging.DifferCallback
@ -30,7 +28,6 @@ import androidx.paging.ItemSnapshotList
import androidx.paging.LoadState
import androidx.paging.LoadStates
import androidx.paging.NullPaddedList
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingDataDiffer
import kotlinx.coroutines.Dispatchers
@ -38,46 +35,28 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
@Composable
fun <T : Any> Flow<PagingData<T>>.collectAsLazyPagingItems(): LazyPagingItems<T> {
val lazyPagingItems = remember(this) { LazyPagingItems(this) }
LaunchedEffect(lazyPagingItems) { lazyPagingItems.collectPagingData() }
LaunchedEffect(lazyPagingItems) { lazyPagingItems.collectLoadState() }
return lazyPagingItems
}
fun <T : Any> LazyListScope.items(
items: LazyPagingItems<T>,
key: ((item: T) -> Any)? = null,
itemContent: @Composable LazyItemScope.(value: T?) -> Unit
) {
items(
count = items.itemCount,
key =
if (key == null) null
else
{ index ->
val item = items.peek(index)
if (item == null) {
PagingPlaceholderKey(index)
} else {
key(item)
}
}
) { index -> itemContent(items[index]) }
}
class LazyPagingItems<T : Any>
/**
* The class responsible for accessing the data from a [Flow] of [PagingData]. In order to obtain an
* instance of [LazyPagingItems] use the [collectAsLazyPagingItems] extension method of [Flow] with
* [PagingData]. This instance can be used by the [items] and [itemsIndexed] methods inside
* [LazyListScope] to display data received from the [Flow] of [PagingData].
*
* @param T the type of value used by [PagingData].
*/
public class LazyPagingItems<T : Any>
internal constructor(
/** the [Flow] object which contains a stream of [PagingData] elements. */
private val flow: Flow<PagingData<T>>
) {
private val mainDispatcher = Dispatchers.Main
/** Contains the latest items list snapshot collected from the [flow]. */
private var itemSnapshotList by mutableStateOf(ItemSnapshotList<T>(0, 0, emptyList()))
/**
* Contains the immutable [ItemSnapshotList] of currently presented items, including any
* placeholders if they are enabled. Note that similarly to [peek] accessing the items in a list
* will not trigger any loads. Use [get] to achieve such behavior.
*/
var itemSnapshotList by mutableStateOf(ItemSnapshotList<T>(0, 0, emptyList()))
private set
/** The number of items which can be accessed. */
val itemCount: Int
@ -109,7 +88,6 @@ internal constructor(
override suspend fun presentNewList(
previousList: NullPaddedList<T>,
newList: NullPaddedList<T>,
newCombinedLoadStates: CombinedLoadStates,
lastAccessedIndex: Int,
onListPresentable: () -> Unit
): Int? {
@ -134,23 +112,6 @@ internal constructor(
return itemSnapshotList[index]
}
/**
* Returns the state containing the item specified at [index] and notifies Paging of the item
* accessed in order to trigger any loads necessary to fulfill [PagingConfig.prefetchDistance].
*
* @param index the index of the item which should be returned.
* @return the state containing the item specified at [index] or null if the item is a placeholder
* or [index] is not within the correct bounds.
*/
@Composable
@Deprecated(
"Use get() instead. It will return you the value not wrapped into a State",
ReplaceWith("this[index]")
)
fun getAsState(index: Int): State<T?> {
return rememberUpdatedState(get(index))
}
/**
* Returns the presented item at the specified position, without notifying Paging of the item
* access that would normally trigger page loads.
@ -162,14 +123,6 @@ internal constructor(
return itemSnapshotList[index]
}
/**
* Returns a new [ItemSnapshotList] representing the currently presented items, including any
* placeholders if they are enabled.
*/
fun snapshot(): ItemSnapshotList<T> {
return itemSnapshotList
}
/**
* Retry any failed load requests that would result in a [LoadState.Error] update to this
* [LazyPagingItems].
@ -228,4 +181,100 @@ private val IncompleteLoadState = LoadState.NotLoading(false)
private val InitialLoadStates =
LoadStates(IncompleteLoadState, IncompleteLoadState, IncompleteLoadState)
data class PagingPlaceholderKey(private val index: Int)
/**
* Collects values from this [Flow] of [PagingData] and represents them inside a [LazyPagingItems]
* instance. The [LazyPagingItems] instance can be used by the [items] and [itemsIndexed] methods
* from [LazyListScope] in order to display the data obtained from a [Flow] of [PagingData].
*
* @sample androidx.paging.compose.samples.PagingBackendSample
*/
@Composable
public fun <T : Any> Flow<PagingData<T>>.collectAsLazyPagingItems(): LazyPagingItems<T> {
val lazyPagingItems = remember(this) { LazyPagingItems(this) }
LaunchedEffect(lazyPagingItems) { lazyPagingItems.collectPagingData() }
LaunchedEffect(lazyPagingItems) { lazyPagingItems.collectLoadState() }
return lazyPagingItems
}
/**
* Adds the [LazyPagingItems] and their content to the scope. The range from 0 (inclusive) to
* [LazyPagingItems.itemCount] (exclusive) always represents the full range of presentable items,
* because every event from [PagingDataDiffer] will trigger a recomposition.
*
* @sample androidx.paging.compose.samples.ItemsDemo
*
* @param items the items received from a [Flow] of [PagingData].
* @param key a factory of stable and unique keys representing the item. Using the same key for
* multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
* Android. If null is passed the position in the list will represent the key. When you specify the
* key the scroll position will be maintained based on the key, which means if you add/remove items
* before the current visible item the item with the given key will be kept as the first visible
* one.
* @param itemContent the content displayed by a single item. In case the item is `null`, the
* [itemContent] method should handle the logic of displaying a placeholder instead of the main
* content displayed by an item which is not `null`.
*/
public fun <T : Any> LazyListScope.items(
items: LazyPagingItems<T>,
key: ((item: T) -> Any)? = null,
itemContent: @Composable LazyItemScope.(value: T?) -> Unit
) {
items(
count = items.itemCount,
key =
if (key == null) null
else
{ index ->
val item = items.peek(index)
if (item == null) {
PagingPlaceholderKey(index)
} else {
key(item)
}
}
) { index -> itemContent(items[index]) }
}
/**
* Adds the [LazyPagingItems] and their content to the scope where the content of an item is aware
* of its local index. The range from 0 (inclusive) to [LazyPagingItems.itemCount] (exclusive)
* always represents the full range of presentable items, because every event from
* [PagingDataDiffer] will trigger a recomposition.
*
* @sample androidx.paging.compose.samples.ItemsIndexedDemo
*
* @param items the items received from a [Flow] of [PagingData].
* @param key a factory of stable and unique keys representing the item. Using the same key for
* multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
* Android. If null is passed the position in the list will represent the key. When you specify the
* key the scroll position will be maintained based on the key, which means if you add/remove items
* before the current visible item the item with the given key will be kept as the first visible
* one.
* @param itemContent the content displayed by a single item. In case the item is `null`, the
* [itemContent] method should handle the logic of displaying a placeholder instead of the main
* content displayed by an item which is not `null`.
*/
public fun <T : Any> LazyListScope.itemsIndexed(
items: LazyPagingItems<T>,
key: ((index: Int, item: T) -> Any)? = null,
itemContent: @Composable LazyItemScope.(index: Int, value: T?) -> Unit
) {
items(
count = items.itemCount,
key =
if (key == null) null
else
{ index ->
val item = items.peek(index)
if (item == null) {
PagingPlaceholderKey(index)
} else {
key(index, item)
}
}
) { index -> itemContent(index, items[index]) }
}
private data class PagingPlaceholderKey(private val index: Int)