Hi everyone, I have a question here. Is there any ...
# compose
u
Hi everyone, I have a question here. Is there any guarantee among order of statements of composable functions, order of composable widgets being drawn on the screen, and the order of measurables passed to MeasurePolicy.measure ?
v
• Composable functions can execute in any order.
• Composable functions can execute in parallel.
• Recomposition skips as many composable functions and lambdas as possible.
• Recomposition is optimistic and may be canceled.
• A composable function might be run quite frequently, as often as every frame of an animation.
https://developer.android.com/jetpack/compose/mental-model So no guarantees about execution order. You can control drawing order with Box and zIndex (at least). Not sure about measuring • https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Box(androidx.compose.ui[…]oolean,kotlin.Function1)https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier#(androidx.compose.ui.Modifier).zIndex(kotlin.Float)
u
I have read about the execution order in the docs, and built a sample page to figure out if any connection between execution order and drawing order:
Copy code
Box( modifier = Modifier.fillMaxSize().padding(it)) {
    Box(contentAlignment = Alignment.Center) {
        var ticks by remember {
            mutableStateOf(0)
        }
        val color1 by remember {
            derivedStateOf { ticks % 4 in 1..2 }
        }
        val color2 by remember {
            derivedStateOf { ticks % 4 < 2 }
        }
        LaunchedEffect(Unit) {
            while (true) {
                delay(500L)
                ticks++
            }
        }
        ColorBox(100.dp, if (color1) {Color.Blue} else {Color.Red})
        ColorBox(50.dp, if (color2) {Color.Green} else {Color.Yellow})
    }
}

@Composable
fun ColorBox(size: Dp, color: Color) {
    Box(
        modifier = Modifier.size(size).background(color)
    )
SideEffect {
        Log.i("ColorBox", "ColorBox size $size color ${color.toArgb()}")
    }
}
On tick's increatment, only one ColorBox is updated and recomposed (and called), but the 50.dp box is always on the top of 100.dp box. Maybe I can draw a conclusion that drawing order of composable widgets is exactly the same as their statement order (in the most common case)?
e
No you absolutely cannot make that assumption.
Drawing order is based on whatever container/layout in which the layout nodes are in. In standard layout containers like box, row & column, its based on composition order, with modifier.zIndex affecting placement order. but any arbitrary layout container can rearrange the layout nodes in any order it likes.
u
Does composition order have the same meaning as statement order?
👌 1
By customizing a
Layout
block, found that drawing order is the same as the order container calls
Placeable.place
, and statement order is the order of measurables passed to MeasurePolicy.measure
e
Exactly. Thats why you can compose in any order (statement order == order of measurables) but any parent layout can take that list and place them in any arbitrary order
z
Also “happens to work that way in a particular code snippet at a particular time” is very different than “is an explicit guarantee of the library’s contract”
1