Reputation: 843
I'm currently using paging items (LazyPagingItems
) in LazyVerticalGrid
via below extention function and it works fine.
inline fun <T : Any> LazyGridScope.items(
items: LazyPagingItems<T>,
crossinline itemContent: @Composable LazyGridItemScope.(item: T?) -> Unit
) {
items(count = items.itemCount) { index ->
itemContent(items[index])
}
}
However, i want to make use of other parameters that LazyLazyout
provides like key
, span
etc and tried below function.
inline fun <T : Any> LazyGridScope.items(
items: LazyPagingItems<T>,
noinline key: ((item: T?) -> Any)? = null,
noinline span: (LazyGridItemSpanScope.(item: T?) -> GridItemSpan)? = null,
noinline contentType: (item: T?) -> Any? = { null },
crossinline itemContent: @Composable LazyGridItemScope.(item: T?) -> Unit
) = items(
count = items.itemCount,
key = if (key != null) { index: Int -> key(items[index]) } else null,
span = if (span != null) { { span(items[it]) } } else null,
contentType = { index: Int -> contentType(items[index]) }
) {
itemContent(items[it])
}
When i use that function with key
, it shows errors that Type mismatch: inferred type is Long? but Any was expected
.
items(items = products, key = { product -> product?.productId }) {
//Content
}
I guess this is due to declaration of public class LazyPagingItems<T : Any>
. How do I resolve it to use all parameters with paging items ?
Upvotes: 3
Views: 2827
Reputation: 806
I struggle with a "Key" problem since I updated from androidx.compose "1.3.0-beta03" to "1.3.0-rc01".
I use LazyPagingItems for a LazyVerticalGrid and i add items like this in the LazyGridScope:
(pagingData: Flow<PagingData<DangerItem>>){
val feedData = pagingData.collectAsLazyPagingItems()
items(feedData.itemCount,
// to maximize the performance add a unique key
// as fallback use index of element
key = { index ->
feedData[index]?.code ?: index
},
contentType = { idx ->
if (feedData[idx] != null) 1 else 0
}
)
But since the library update, when I filter the content (so the paging items are updated in the flow), it throws an Exception. This exception wasn't thrown in the beta03 library version.
java.lang.IllegalArgumentException: Failed requirement.
at androidx.compose.foundation.lazy.grid.LazyGridSpanLayoutProvider.getLineIndexOfItem--_Ze7BM(LazyGridSpanLayoutProvider.kt:174)
at androidx.compose.foundation.lazy.grid.LazyGridItemPlacementAnimatorKt.lastIndexInPreviousLineBefore(LazyGridItemPlacementAnimator.kt:489)
at androidx.compose.foundation.lazy.grid.LazyGridItemPlacementAnimatorKt.access$lastIndexInPreviousLineBefore(LazyGridItemPlacementAnimator.kt:1)
Because paging data is changing and elements become null while loading I can't supply a unique key, the App crashes. Is this now a bug in the library or what exactly is the best practice when using LazyPagingItems that can change over time.
I found this workaround.
key = { idx ->
if (feedData[feedData.itemCount - 1] == null || feedData.itemCount <= 1) idx
else feedData[idx]?.code ?: idx
},
Upvotes: 0
Reputation: 87605
With product?.productId
you are trying to pass an optional Int?
value, while key
expects a non-optional Any
value.
When you pass key = null
to the computation block, under the hood it creates a unique key for each object depending on the index. A particular item key cannot be null
as that would make it equal to other item keys, which is forbidden.
You can make call key
only for non optional items, and provide index
as the default value for optional case:
inline fun <T : Any> LazyGridScope.items(
// ...
noinline key: ((item: T) -> Any)? = null,
// ...
) = items(
// ...
key = if (key != null) { index: Int -> items[index]?.let(key) ?: index } else null,
// ...
Usage:
items(items = products, key = { product -> product.productId }) {
Upvotes: 1