Home > database >  Measure child composables in a background thread
Measure child composables in a background thread

Time:11-06

I want to create a @Composable layout that places its child composables in a specific way. For this it needs to know the Constraints, for instance maxWidth and maxHeight. But the calculation of the children's sizes and positions might be heavy in case of huge datasets. Is there a way to perform this calculation in a background thread and then "post" the MeasureResult back? The code looks like this:

Layout(
    content = {
        data.forEach { node ->
            ItemContent(node)
        }
    },
) { measurables, constraints ->
    val nodes = measurer.measureNodes( // I want to do this in background
        data,
        constraints.maxWidth,
        constraints.maxHeight,
    )
    val placeables = measurables.mapIndexed { index, measurable ->
        measurable.measure(Constraints.fixed(nodes[index].width, nodes[index].height))
    }
    layout(constraints.maxWidth, constraints.maxHeight) {
        placeables.forEachIndexed { index, placeable ->
            placeable.placeRelative(nodes[index].offsetX, nodes[index].offsetY)
        }
    }
}

The problem is, you can't launch a coroutine inside the measure block, and you can't wrap the whole Layout composable in a coroutine scope as it needs to be called from a composable scope. I can't figure out how to do this

CodePudding user response:

I don't know what you are thinking here, but you should really refer to the docs. All the UI rendering in Compose is asynchronous, so you should not worry about explicitly creating coroutines here or spawning new threads.

CodePudding user response:

UIs shouldn't be displaying "huge datasets" all at once. Doing so is a poor design. If it's list of items, you can use LazyColumn, which is intended to only load and display a limited set of items at a time.

If it's not a list and you are creating one huge container - as it appears to be the case in your sample code - then you need to reconsider the layout, like separating the data into tabs. Alternatively, you can still use a LazyColumn even if the items are not the same. Without knowing what your UI looks like, it's not possible to provide any realistic suggestion.

Measuring stuff in the background doesn't make sense, since Compose internally handles measurements quite well, even when there are a lot of items that need to be displayed.

  • Related