Alexander Maryanovsky
04/02/2022, 11:07 AMforEach
for @Composable
functions?/**
* Like Kotlin's [Iterable.forEach], but the action is not inlined, and is [Composable].
* This makes it better when used in a [Composable] function when each iteration accesses a [State]. When using the
* regular, inlined `forEach`, whenever one of the states accessed changes, the entire function (and the entire loop)
* will be recomposed. Whereas with a non-inlined `forEach`, only the iteration with the state that changed will be
* recomposed.
*/
@Composable
fun <T> Iterable<T>.forEachComposable(action: @Composable (T) -> Unit) {
for (element in this) action(element)
}
Adam Powell
04/02/2022, 2:51 PMaction
behave, and introducing two layers of composable function calls (forEachComposable
plus action
in each iteration) isn't free either. Any time you use this you're placing a bet that whatever action
is doing is expensive enough to make it worth it, and that the composables action
calls aren't themselves eligible for skipping, which would optimize the invalidation case that forEachComposable
looks to solve.Alexander Maryanovsky
04/03/2022, 6:52 AMclass Counter(
val number: Int
){
fun next() = Counter(number+1)
}
val counters = (1..20).map { MutableStateFlow(Counter(0)) }.toMutableList()
fun main() {
singleWindowApplication(
title = "Text",
state = WindowState(
width = 800.dp,
height = 400.dp,
)
) {
Column (
modifier = Modifier.fillMaxWidth()
){
for (i in counters.indices){
val counter by counters[i].collectAsState()
ListItem(
counter = counter,
modifier = Modifier
.recomposeHighlighter()
.clickable {
counters[i].value = counter.next()
}
)
}
}
}
}
@Composable
fun ListItem(
counter: Counter,
modifier: Modifier
){
Text(
text = "Count: ${counter.number}",
modifier = modifier
)
}