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

Jetpack Compose 相同参数创建的Modifier为何会触发不必要重组?

问题解答

关于Modifier的Stable特性疑问

Modifier接口虽然被标记为@Stable,但Stable标记仅代表该类型的等值性变化可被Compose编译器追踪,不代表逻辑相同的不同Modifier实例会被判定为相等。
你在重组时为未选中标签重新构建的Modifier,虽然逻辑参数完全一致,但绝大多数Modifier元素(比如clip、shadow、border等)没有重写equals方法,因此新生成的Modifier实例和旧实例的equals比对返回false,Compose会认为Test的入参发生了变化,触发不必要的重组。
你把Modifier移入Test内部时,Test的入参变为了title:Int、tab、selectedTab这类默认Stable/Immutable的类型,只要这些入参没有变化,Compose就会跳过Test的重组,Modifier的构建逻辑仅在Test真正需要重组时才会执行,因此符合你的预期。

无需移入Modifier的解决方案

你可以通过remember缓存每个标签的Modifier实例,仅当依赖的状态发生变化时才重新计算Modifier,就可以避免不必要的重组:

tabs.forEach { tab ->
    Log.d("MyTab", "${tab.title}-${tab == selectedTab}")
    // 仅当tab或selectedTab变化时,才重新计算当前tab的Modifier
    val tabModifier = remember(tab, selectedTab) {
        Modifier
            .clip(RoundedCornerShape(8.dp))
            .padding(horizontal = 8.dp)
            .shadow(0.5.dp, RoundedCornerShape(8.dp))
            .background(MaterialTheme.colors.surface)
            .border(1.dp,
                if (tab==selectedTab) MaterialTheme.appColors.bottomTabSelect else Color.Transparent,
                RoundedCornerShape(8.dp))
            .clickable {
                if (tab==selectedTab) {
                    // already selected
                    return@clickable
                }
                onTabSelected(tab)
            }
            .padding(8.dp)
    }

    Test(tab.title, tabModifier)
}

这种实现下,只有选中状态发生变化的两个标签(旧选中、新选中)的remember依赖项selectedTab会触发Modifier重新计算,其余标签的Modifier实例保持不变,Test的入参没有变化,就会被Compose跳过重组,完全符合你的性能需求。

内容的提问来源于stack exchange,提问作者Jemshit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 06:30:04