开启强跳过模式后Composable仍重组:Lambda对重组跳过的影响问询
Compose中Lambda对组件重组跳过的影响问题
我已使用Kotlin 2.0.0、2.0.10-RC及1.9.20版本测试,排除了Kotlin编译器异常问题。但目前无法理解Lambda如何影响使用该Lambda的组件的重组跳过能力。我为项目生成了Compose Compiler Metrics,所有组件和类(包括Lambda)均被标记为skippable和stable。
当前可正常跳过重组的代码
@Composable fun CounterScreen(presenter: CounterPresenter) { val state = presenter.present() CounterContent(state) } @Composable private fun CounterContent(state: CounterState) { // 通过remember保存lambda,确保按钮重组被跳过 val increment = remember { { state.eventSink(CounterEvent.Increment) } } val decrement = remember { { state.eventSink(CounterEvent.Decrement) } } Scaffold(content = { paddingValues -> Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column( modifier = Modifier.padding(paddingValues), horizontalAlignment = Alignment.CenterHorizontally, ) { TextButton(onClick = increment) { Text("Increment") } Text("Count: ${state.count}") Text(state.message) TextButton(onClick = decrement) { Text("Decrement") } } } }) }
Presenter、State、Event实现代码
sealed interface CounterEvent : Event { data object Increment : CounterEvent data object Decrement : CounterEvent } class CounterPresenter : Presenter<CounterState> { @Composable override fun present(): CounterState { var count by rememberSaveable { mutableIntStateOf(0) } val message by remember { derivedStateOf { when { count < 0 -> "Counter is less than 0" count > 0 -> "Counter is greater than 0" else -> "Counter is 0" } } } return CounterState( count = count, message = message, eventSink = { event -> when (event) { Increment -> count += 1 Decrement -> count -= 1 } } ) } } data class CounterState( val count: Int, val message: String, override val eventSink: (CounterEvent) -> Unit, ) : State<CounterEvent>
测试结果与问题
点击Increment按钮10次后,重组计数显示按钮被正确跳过。理论上开启强跳过模式后,可移除remember调用,直接传递Lambda来避免重组,但实际情况并非如此:移除remember并开启强跳过模式后,按钮会随count变化每次都重组,对应的代码如下:
@Composable private fun CounterContent(state: CounterState) { Scaffold(content = { paddingValues -> Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column( modifier = Modifier.padding(paddingValues), horizontalAlignment = Alignment.CenterHorizontally, ) { TextButton(onClick = { state.eventSink(CounterEvent.Increment) }) { Text("Increment") } Text("Count: ${state.count}") Text(state.message) TextButton(onClick = { state.eventSink(CounterEvent.Decrement) }) { Text("Decrement") } } } }) }
内容的提问来源于stack exchange,提问作者Andre Thiele
相关产品推荐
相关产品推荐

