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

HorizontalPageIndicator滑动时三次重组是否正常?代码是否有误?

滑动HorizontalPager时HorizontalPageIndicator触发3次重组的原因及优化

这种现象属于正常状态更新范围内的情况,但你的代码写法存在可优化点,能减少不必要的重组次数,具体说明如下:

为什么会触发多次重组?

滑动过程中,PagerState的核心状态会持续更新:

  • 滑动开始时,currentPageOffsetFraction从0开始变化,触发第一次状态更新;
  • 滑动过半切换页面时,currentPage数值变化,触发第二次更新;
  • 滑动结束时,currentPageOffsetFraction回归0,触发第三次更新。

但你的代码里,每次derivedStateOf计算都会创建匿名的PageIndicatorState对象——Compose判断重组的依据是参数的引用或值是否变化,匿名对象每次都是新实例,哪怕内部属性值没变化,也会被判定为参数更新,导致HorizontalPageIndicator额外触发重组。

优化方案:使用稳定的状态实现

把匿名的PageIndicatorState替换为稳定的数据类实现,data class的equals方法会基于属性值判断是否相等,只有当属性真正变化时,才会生成新实例,避免不必要的重组。

优化后的代码:

// 定义稳定的PageIndicatorState实现
data class DefaultPageIndicatorState(
    override val pageCount: Int,
    override val pageOffset: Float,
    override val selectedPage: Int
) : PageIndicatorState

@Composable
fun HouseholdScreen(
    isLoading: Boolean,
    households: List<Household>,
    clickOnDevice: (id: String) -> Unit
) {
    val pagerState = rememberPagerState { households.size }

    val pageIndicatorState = remember {
        derivedStateOf {
            DefaultPageIndicatorState(
                pageCount = pagerState.pageCount,
                pageOffset = pagerState.currentPageOffsetFraction,
                selectedPage = pagerState.currentPage
            )
        }
    }

    HorizontalPager(
        state = pagerState,
        key = { households[it].id }
    ) { page ->
        HouseholdScreen(
            isLoading = isLoading,
            household = households[page]
        ) { deviceId ->
            clickOnDevice(deviceId)
        }
    }

    HorizontalPageIndicator(
        pageIndicatorState = pageIndicatorState.value,
        modifier = Modifier.padding(4.dp)
    )
}

优化后的效果

优化后,HorizontalPageIndicator只会在pageCount、currentPageOffsetFraction或currentPage真正变化时重组,滑动过程中必要的动画更新仍会保留,但不会因为对象引用变化触发额外重组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:37:02