为什么Jetpack Compose中操作局部变量的函数可得到正确结果?Code B是否正确?
问题解答
1、为什么Code A测试时始终得到正确结果
你当前测试场景下只触发了初始组合,没有触发过重组,所以看起来结果正常:
- Code A中的
items是普通局部变量,每次ListWithBug执行时都会被初始化为0 - 初始组合阶段,所有组合代码都会全量执行,Column循环遍历10个元素时,
items++完整执行了10次,最终items值为10,和预期一致
一旦触发重组(比如新增可点击按钮修改页面状态,触发ListWithBug重新执行),就会出现错误:
- 重组时Compose会跳过输入没有变化的组件,此时Column中所有
Text的输入参数都没有变化,会被跳过执行,对应的items++也不会执行,最终items的值会停留在初始化的0,显示结果错误 - 更复杂的重组场景下,Compose的执行顺序、跳过规则都是不可预测的,局部变量的计数结果会完全不符合预期。
2、Code B的写法是否正确
完全错误,问题比Code A更严重:
items被声明为remember包裹的状态变量,重组时不会被重置初始值,每次重组只要循环里的代码执行,items就会被额外累加一次:初始组合后值为10,第一次重组后变成20,第二次变成30,数值会持续漂移,完全不符合预期- 你在组合过程中修改了
items状态,而items又被下方的Text读取,这会触发无限重组循环:修改items→ 触发重组 → 再次修改items→ 再次触发重组,最终会导致页面卡死、ANR - 本质上两种写法都属于在组合过程中引入了副作用,违反了Compose可组合函数必须无副作用的原则,这类计数需求应该直接用
myList.size,如果需要做额外的副作用操作,必须使用SideEffect、LaunchedEffect等官方提供的副作用API包裹,不能直接写在组合流程中。
内容的提问来源于stack exchange,提问作者HelloCW
相关产品推荐
相关产品推荐

