Alexander Maryanovsky
04/02/2022, 11:07 AMforEach for @Composable functions?Alexander Maryanovsky
04/02/2022, 11:08 AM/**
* 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 AMAlexander Maryanovsky
04/03/2022, 6:53 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
)
}Alexander Maryanovsky
04/03/2022, 6:53 AM