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

如何避免变量变为Action.IDLE时触发Jetpack Compose重组?

问题描述

我在代码中用remember声明了一个变量:

val action = remember { mutableStateOf(Action.FRESH) }

action的可选值为**(FRESH, SEARCH, IDLE)。我希望当action变为Action.IDLE**时避免触发重组,但其他值变更时正常触发重组。

我读取action值的逻辑如下:

val listOfItems = when (action) {
    Action.FRESH -> {
        action = Action.IDLE
        // 从服务器获取初始数据
    }

    Action.SEARCH -> {
        action = Action.IDLE
        // 从服务器获取搜索数据
    }

    else -> {
        // 什么都不做
    }
}

我不想因action为IDLE时触发重组,这样就不用在else分支给listOfItems设置空值。我尝试过给remember添加key,也用过derivedStateOf,但都未达到预期效果。请问有什么解决思路?

解决思路

方法1:自定义非IDLE触发的MutableState

封装一个自定义的MutableState实现,仅当新值不是Action.IDLE时才通知重组,设置为IDLE时直接更新值但不触发组件刷新:

class NonIdleActionState(initialValue: Action) : MutableState<Action> {
    private val delegate = mutableStateOf(initialValue)
    override var value: Action
        get() = delegate.value
        set(newValue) {
            if (newValue != Action.IDLE) {
                delegate.value = newValue
            } else {
                delegate.value = newValue
            }
        }

    override fun component1(): Action = delegate.component1()
    override fun component2(): (Action) -> Unit = delegate.component2()
}

// 使用方式
val action = remember { NonIdleActionState(Action.FRESH) }

方法2:用derivedStateOf过滤IDLE状态

通过derivedStateOf创建一个仅包含非IDLE值的状态,只有当这个状态变化时才触发重组,同时用remember缓存listOfItems的结果:

val action = remember { mutableStateOf(Action.FRESH) }
val listOfItems = remember { mutableStateOf(emptyList<Item>()) }

// 仅当action非IDLE时才更新,触发重组
val effectiveAction = remember {
    derivedStateOf {
        if (action.value != Action.IDLE) action.value else null
    }
}.value

when (effectiveAction) {
    Action.FRESH -> {
        action.value = Action.IDLE
        listOfItems.value = // 从服务器获取初始数据
    }
    Action.SEARCH -> {
        action.value = Action.IDLE
        listOfItems.value = // 从服务器获取搜索数据
    }
    null -> {} // 保持原有数据,不做操作
}

// 直接使用listOfItems.value即可

方法3:将数据逻辑放到LaunchedEffect中

把网络请求这类副作用放到LaunchedEffect里,仅当action为非IDLE时执行逻辑,设置为IDLE时不会触发重组:

val action = remember { mutableStateOf(Action.FRESH) }
val listOfItems = remember { mutableStateOf(emptyList<Item>()) }

LaunchedEffect(action.value) {
    when (action.value) {
        Action.FRESH -> {
            listOfItems.value = // 获取初始数据
            action.value = Action.IDLE
        }
        Action.SEARCH -> {
            listOfItems.value = // 获取搜索数据
            action.value = Action.IDLE
        }
        Action.IDLE -> {} // 无操作
    }
}

// 直接使用listOfItems.value,不会因action变为IDLE触发重组

内容的提问来源于stack exchange,提问作者Mohamed Abu Zaid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 23:27:40