You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中size变量无法随width/height正确更新的问题求助

Jetpack Compose中size变量无法随width/height正确更新的问题求助

嘿,我完全懂你碰到的这个坑!这其实是Jetpack Compose状态管理里很常见的一个误区,我当初学的时候也踩过类似的雷~

先给你拆解问题根源:你现在定义的var size = Size(width, height)只是个普通的局部变量。虽然每次Composable重组(比如width变化时)这行代码会重新执行,但有两个关键问题:

  • 它不是状态变量,没法主动通知依赖它的地方更新;
  • 像pointerInput里的lambda是稳定的——因为你传的参数是Unit,这个lambda只会被初始化一次,它捕获的是最初的size快照,后续重组时的新值根本传不进去,所以你打印的永远是初始的Size(0,0)。

那怎么解决呢?最靠谱的方式是用derivedStateOf创建派生状态,它能自动跟踪依赖的状态变化,同步更新计算结果。给你改好的代码:

@Composable
@Preview
fun App() {
    var width by remember { mutableStateOf(0f) }
    var height by remember { mutableStateOf(0f) }
    
    // 用derivedStateOf包裹计算逻辑,自动跟踪width和height的变化
    val size by remember {
        derivedStateOf {
            Size(width, height)
        }
    }

    Button(
        onClick = { width++ },
        modifier = Modifier.pointerInput(Unit) {
            detectDragGestures { change, dragAmount ->
                println(size) // 现在能拿到最新的size值了
                println(width)
            }
        }
    ) {
        Text("Increase Width")
    }
}

为什么这样就生效了?

  • derivedStateOf会监听width和height的变化,只要其中一个变了,就会重新计算Size(width, height);
  • 用by remember委托后,size变成了一个可观察的状态变量,不管是在UI里用,还是在pointerInput的lambda里访问,拿到的永远是最新的值。

另外还有个更简单的场景:如果你的size只在UI渲染时用(比如给某个组件设置尺寸),其实可以直接在需要的地方写Size(width, height),每次重组时都会自动计算最新值。但如果要在多个地方复用,或者像你这样要在手势回调里用,derivedStateOf是最优解,既能保证同步,又能避免不必要的重复计算。

备注:内容来源于stack exchange,提问作者Abdo21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 09:48:09