LazyLayoutPrefetchState


State for lazy items prefetching, used by lazy layouts to instruct the prefetcher.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.layout.LazyLayout
import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
import androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.dp

val items = remember { (0..100).toList().map { it.toString() } }
var currentHandle = remember<LazyLayoutPrefetchState.PrefetchHandle?> { null }
val prefetchState = remember { LazyLayoutPrefetchState() }
// Create an item provider
val itemProvider = remember {
    {
        object : LazyLayoutItemProvider {
            override val itemCount: Int
                get() = 100

            @Composable
            override fun Item(index: Int, key: Any) {
                Box(
                    modifier =
                        Modifier.width(100.dp)
                            .height(100.dp)
                            .background(color = if (index % 2 == 0) Color.Red else Color.Green)
                ) {
                    Text(text = items[index])
                }
            }
        }
    }
}

Column {
    Button(onClick = { currentHandle = prefetchState.schedulePrecomposition(10) }) {
        Text(text = "Prefetch Item 10")
    }
    Button(onClick = { currentHandle?.cancel() }) { Text(text = "Cancel Prefetch") }
    LazyLayout(modifier = Modifier.size(500.dp), itemProvider = itemProvider) { constraints ->
        // plug the measure policy, this is how we create and layout items.
        val placeablesCache = mutableListOf<Pair<Placeable, Int>>()
        fun Placeable.mainAxisSize() = width
        fun Placeable.crossAxisSize() = height

        val childConstraints =
            Constraints(maxWidth = Constraints.Infinity, maxHeight = constraints.maxHeight)

        var currentItemIndex = 0
        var crossAxisSize = 0
        var mainAxisSize = 0

        // measure items until we either fill in the space or run out of items.
        while (mainAxisSize < constraints.maxWidth && currentItemIndex < items.size) {
            val itemPlaceables = compose(currentItemIndex).map { it.measure(childConstraints) }
            for (item in itemPlaceables) {
                // save placeable to be placed later.
                placeablesCache.add(item to mainAxisSize)

                mainAxisSize += item.mainAxisSize() // item size contributes to main axis size
                // cross axis size will the size of tallest/widest item
                crossAxisSize = maxOf(crossAxisSize, item.crossAxisSize())
            }
            currentItemIndex++
        }

        val layoutWidth = minOf(mainAxisSize, constraints.maxHeight)
        val layoutHeight = crossAxisSize

        layout(layoutWidth, layoutHeight) {
            // since this is a linear list all items are placed on the same cross-axis position
            for ((placeable, position) in placeablesCache) {
                placeable.place(position, 0)
            }
        }
    }
}

Summary

Nested types

A handle to control some aspects of the prefetch request.

A scope for schedulePrecompositionAndPremeasure callbacks.

Public constructors

Cmn

State for lazy items prefetching, used by lazy layouts to instruct the prefetcher.

Cmn
@ExperimentalFoundationApi
LazyLayoutPrefetchState(
    prefetchScheduler: PrefetchScheduler?,
    onNestedPrefetch: (NestedPrefetchScope.() -> Unit)?
)

This function is deprecated. Please use overload without Prefetch Scheduler.

Cmn

Public functions

LazyLayoutPrefetchState.PrefetchHandle
schedulePrecomposition(index: @IntRange(from = 0) Int)

Schedules precomposition for the new item.

Cmn
LazyLayoutPrefetchState.PrefetchHandle
schedulePrecompositionAndPremeasure(
    index: @IntRange(from = 0) Int,
    constraints: Constraints,
    onItemPremeasured: (LazyLayoutPrefetchState.PrefetchResultScope.() -> Unit)?
)

Schedules precomposition and premeasure for the new item.

Cmn

Public constructors

LazyLayoutPrefetchState

LazyLayoutPrefetchState()

LazyLayoutPrefetchState

@ExperimentalFoundationApi
LazyLayoutPrefetchState(onNestedPrefetch: (NestedPrefetchScope.() -> Unit)? = null)

State for lazy items prefetching, used by lazy layouts to instruct the prefetcher.

Parameters
onNestedPrefetch: (NestedPrefetchScope.() -> Unit)? = null

a callback which will be invoked when this LazyLayout is prefetched in context of a parent LazyLayout, giving a chance to recursively prefetch its own children. See NestedPrefetchScope.

LazyLayoutPrefetchState

@ExperimentalFoundationApi
LazyLayoutPrefetchState(
    prefetchScheduler: PrefetchScheduler? = null,
    onNestedPrefetch: (NestedPrefetchScope.() -> Unit)? = null
)

State for lazy items prefetching, used by lazy layouts to instruct the prefetcher.

Parameters
prefetchScheduler: PrefetchScheduler? = null

the PrefetchScheduler implementation to use to execute prefetch requests. If null is provided, the default PrefetchScheduler for the platform will be used.

onNestedPrefetch: (NestedPrefetchScope.() -> Unit)? = null

a callback which will be invoked when this LazyLayout is prefetched in context of a parent LazyLayout, giving a chance to recursively prefetch its own children. See NestedPrefetchScope.

Public functions

schedulePrecomposition

fun schedulePrecomposition(index: @IntRange(from = 0) Int): LazyLayoutPrefetchState.PrefetchHandle

Schedules precomposition for the new item. If you also want to premeasure the item please use schedulePrecompositionAndPremeasure instead. This function should only be called once per item. If the item has already been composed at the time this request executes, either from a previous call to this function or because the item is already visible, this request should have no meaningful effect.

Parameters
index: @IntRange(from = 0) Int

item index to prefetch.

Returns
LazyLayoutPrefetchState.PrefetchHandle

A PrefetchHandle which can be used to control the lifecycle of the prefetch request. Use PrefetchHandle.cancel to cancel the request or PrefetchHandle.markAsUrgent to mark the request as urgent.

schedulePrecompositionAndPremeasure

fun schedulePrecompositionAndPremeasure(
    index: @IntRange(from = 0) Int,
    constraints: Constraints,
    onItemPremeasured: (LazyLayoutPrefetchState.PrefetchResultScope.() -> Unit)? = null
): LazyLayoutPrefetchState.PrefetchHandle

Schedules precomposition and premeasure for the new item. This should be used instead of schedulePrecomposition if you also want to premeasure the item. This function should only be called once per item. If the item has already been composed / measured at the time this request executes, either from a previous call to this function or because the item is already visible, this request should have no meaningful effect.

Parameters
index: @IntRange(from = 0) Int

item index to prefetch.

constraints: Constraints

Constraints to use for premeasuring.

onItemPremeasured: (LazyLayoutPrefetchState.PrefetchResultScope.() -> Unit)? = null

This callback is called when the item premeasuring is finished. If the request is canceled or no measuring is performed this callback won't be called. Use PrefetchResultScope.getSize to get the item's size.

Returns
LazyLayoutPrefetchState.PrefetchHandle

A PrefetchHandle which can be used to control the lifecycle of the prefetch request. Use PrefetchHandle.cancel to cancel the request or PrefetchHandle.markAsUrgent to mark the request as urgent.