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

Jetpack Compose中FlowRow异常显示与重复重组问题求助

问题修复方案

一、FlowRow真机仅显示2个筛选按钮的修复

日志显示所有5个分类都在循环中执行,但真机只渲染2个按钮,问题出在布局约束和组件遮挡:

修复步骤

  1. 调整Column对齐方式:移除Column的horizontalAlignment = Alignment.CenterHorizontally,避免约束FlowRow的宽度计算,同时给FlowRow添加wrapContentHeight()确保所有换行后的按钮都能展示:
Column(
    verticalArrangement = Arrangement.Center,
    modifier = Modifier
        .padding(dimensionResource(R.dimen.padding_medium))
        .fillMaxSize(),
) {
    FlowRow(
        horizontalArrangement = Arrangement.Start,
        verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.padding_small)),
        modifier = Modifier
            .fillMaxWidth()
            .wrapContentHeight(),
    ) {
        // 原有按钮循环逻辑
    }
  1. 限制FilterButton宽度:给FilterButton设置最大宽度,避免单个按钮过宽导致换行后空间不足:
FilterButton(
    onFilterButtonClick = onFilterButtonClick,
    filterName = key.first,
    isFilterSelected = key.second,
    modifier = Modifier
        .padding(end = dimensionResource(R.dimen.padding_small))
        .maxWidth(120.dp) // 根据UI需求调整合适值
)

二、Composable重复重组4次的修复

从Rebugger日志可知,重组由三个不稳定参数导致:onClick、onFilterButtonClick每次生成新函数实例,modifier每次创建新Padding实例。

修复步骤

  1. 稳定函数参数:在调用SavedScreen的父Composable中,用remember包裹点击函数,确保实例稳定:
// 父Composable中
val onClick = remember {
    { recommendation: Recommendation, category: CATEGORY ->
        // 你的点击逻辑
    }
}

val onFilterButtonClick = remember {
    { category: CATEGORY, isSelected: Boolean ->
        // 你的筛选按钮逻辑
    }
}
  1. 复用Modifier实例:直接使用传入的modifier,避免在SavedScreen内部重新创建:
Column(
    verticalArrangement = Arrangement.Center,
    modifier = modifier
        .padding(dimensionResource(R.dimen.padding_medium))
        .fillMaxSize(),
)
  1. 优化LazyColumn性能:当前用单个item包裹所有列表内容,会导致整个列表频繁重组,改为按分类拆分items:
LazyColumn(modifier = Modifier.fillMaxSize()) {
    savedRecommendationsMap.forEach { (key, value) ->
        if (key.second) {
            items(value ?: emptyList()) { recommendation ->
                SavedScreenCard(
                    recommendation = recommendation,
                    onClick = onClick,
                    category = key.first,
                )
            }
        }
    }
}

原始代码

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun SavedScreen(
    savedRecommendationsMap: Map<Pair<CATEGORY, Boolean>, List<Recommendation>?>,
    onClick: (Recommendation, CATEGORY) -> Unit,
    onFilterButtonClick: (category: CATEGORY, isSelected: Boolean) -> Unit,
    modifier: Modifier = Modifier,
) {
    Rebugger(
        trackMap = mapOf(
            "savedRecommendationsMap" to savedRecommendationsMap,
            "onClick" to onClick,
            "onFilterButtonClick" to onFilterButtonClick,
            "modifier" to modifier,
        ),
    )
    
    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier
            .padding(dimensionResource(R.dimen.padding_medium))
            .fillMaxSize(),
    ) {
        FlowRow(
            horizontalArrangement = Arrangement.Start,
            verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.padding_small)),
            modifier = Modifier.fillMaxWidth(),
        ) {
            savedRecommendationsMap.forEach() { (key, value) ->
                Log.d(
                    "SavedScreen",
                    "Category: ${key.first}, isSelected: ${key.second}, recommendations: ${value?.size ?: 0}"
                )

                FilterButton(
                    onFilterButtonClick = onFilterButtonClick,
                    filterName = key.first,
                    isFilterSelected = key.second,
                    modifier = Modifier.padding(end = dimensionResource(R.dimen.padding_small)),
                )
            }

        }
        
        HorizontalDivider(
            thickness = 2.dp,
            modifier = Modifier.padding(vertical = dimensionResource(R.dimen.padding_medium)),
        )
        
        if (!savedRecommendationsMap.any { it.value != null }) {
            NothingScreen(modifier = modifier)
        } else {
            LazyColumn(
                modifier = Modifier
                    .fillMaxSize(),
            ) {
                item {
                    savedRecommendationsMap.forEach { (key, value) ->
                        if (key.second == true) {
                            value?.forEach {
                                SavedScreenCard(
                                    recommendation = it,
                                    onClick = onClick,
                                    category = key.first,
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}

截图

预览正常效果:
预览正常的筛选按钮
真机异常效果:
真机仅显示2个筛选按钮

日志信息

Category: COFFEESHOPS, isSelected: true, recommendations: 0
Category: RESTRAUNTS, isSelected: true, recommendations: 0
Category: PARKS, isSelected: true, recommendations: 0
Category: SHOPPINGCENTERS, isSelected: true, recommendations: 0
Category: HOTELS, isSelected: true, recommendations: 0
🐞Rebugger recomposed because 
     `onClick` changed from `Function2<com.example.prguetravel.model.Recommendation, com.example.prguetravel.utils.CATEGORY, kotlin.Unit>` to `Function2<com.example.prguetravel.model.Recommendation, com.example.prguetravel.utils.CATEGORY, kotlin.Unit>`, 
     `onFilterButtonClick` changed from `Function2<com.example.prguetravel.utils.CATEGORY, java.lang.Boolean, kotlin.Unit>` to `Function2<com.example.prguetravel.utils.CATEGORY, java.lang.Boolean, kotlin.Unit>`, 
     `modifier` instance changed, but content remains the same -> `androidx.compose.foundation.layout.PaddingValuesElement@e5200000`
Category: COFFEESHOPS, isSelected: true, recommendations: 0
Category: RESTRAUNTS, isSelected: true, recommendations: 0
Category: PARKS, isSelected: true, recommendations: 0
Category: SHOPPINGCENTERS, isSelected: true, recommendations: 0
Category: HOTELS, isSelected: true, recommendations: 0
🐞 Rebugger activated on `Rebugger`
Category: COFFEESHOPS, isSelected: true, recommendations: 0
Category: RESTRAUNTS, isSelected: true, recommendations: 0
Category: PARKS, isSelected: true, recommendations: 0
Category: SHOPPINGCENTERS, isSelected: true, recommendations: 0
Category: HOTELS, isSelected: true, recommendations: 0
🐞Rebugger recomposed because 
     `onClick` changed from `Function2<com.example.prguetravel.model.Recommendation, com.example.prguetravel.utils.CATEGORY, kotlin.Unit>` to `Function2<com.example.prguetravel.model.Recommendation, com.example.prguetravel.utils.CATEGORY, kotlin.Unit>`, 
     `onFilterButtonClick` changed from `Function2<com.example.prguetravel.utils.CATEGORY, java.lang.Boolean, kotlin.Unit>` to `Function2<com.example.prguetravel.utils.CATEGORY, java.lang.Boolean, kotlin.Unit>`, 
     `modifier` instance changed, but content remains the same -> `androidx.compose.foundation.layout.PaddingValuesElement@e5200000`
Category: COFFEESHOPS, isSelected: true, recommendations: 0
Category: RESTRAUNTS, isSelected: true, recommendations: 0
Category: PARKS, isSelected: true, recommendations: 0
Category: SHOPPINGCENTERS, isSelected: true, recommendations: 0
Category: HOTELS, isSelected: true, recommendations: 0
Category: COFFEESHOPS, isSelected: true, recommendations: 0
Category: RESTRAUNTS, isSelected: true, recommendations: 0
Category: PARKS, isSelected: true, recommendations: 0
Category: SHOPPINGCENTERS, isSelected: true, recommendations: 0
Category: HOTELS, isSelected: true, recommendations: 0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:45:56