如何在Compose Desktop中通过callbackFlow传递Button的onClick点击事件
问题根因
- 你在每次点击按钮时才创建新的
callbackFlow实例赋值给buttonListener,但收集逻辑仅在启动时监听了初始的Flow实例,后续新赋值的Flow没有被收集,自然无法收到后续事件 - 你封装的
offers方法创建的Flow仅支持发送一次数据,本身没有设计为可多次发送事件的数据流
最优实现方案
方案1:使用MutableSharedFlow实现(无需编写扩展,代码最简洁)
MutableSharedFlow是热流,支持多次发送和接收事件,非常适合处理点击这类一次性事件:
// 定义点击事件热流,配置缓冲区处理快速点击场景 private val buttonClickFlow = MutableSharedFlow<Unit>( extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST ) // 收集事件逻辑,建议使用页面生命周期绑定的Scope,避免内存泄漏 // 非Compose场景用 lifecycleScope lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { buttonClickFlow.collect { println("it => Kotlin.Unit") } } } // Compose 场景使用 LaunchedEffect 收集 // LaunchedEffect(Unit) { // buttonClickFlow.collect { // println("it => Kotlin.Unit") // } // } MaterialTheme { Button( onClick = { println("buttonClicked") // 每次点击发送事件 buttonClickFlow.trySend(Unit) } ) { /** 样式设计部分 */ } }
方案2:callbackFlow 标准实现
如果需要使用callbackFlow封装,可以参考以下写法,仅创建一次Flow实例,全程复用:
@Composable fun rememberClickFlow(): Pair<Flow<Unit>, () -> Unit> { return remember { val clickFlow = callbackFlow<Unit> { val onClickAction = { trySend(Unit) } awaitClose { } } clickFlow to { clickFlow.trySend(Unit) } } } // 页面中使用 @Composable fun TestScreen() { val (clickFlow, onButtonClick) = rememberClickFlow() LaunchedEffect(Unit) { clickFlow.collect { println("it => Kotlin.Unit") } } MaterialTheme { Button( onClick = { println("buttonClicked") onButtonClick() } ) { /** 样式设计部分 */ } } }
内容的提问来源于stack exchange,提问作者Ananiya J. Kesto
相关产品推荐
相关产品推荐

