jetpackcompose 中 Flowrow 的意外行为

问题描述 投票:0回答:1

我有一个屏幕,用户可以在其中看到他们从不同类别保存的推荐,并在 FlowRow 的帮助下实现上面的过滤器按钮:

@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 个按钮。此外,当我试图找到解决方案时,我遇到了另一个问题,即该可组合项被重新组合了四次。我使用Rebugger并使用logged来查找原因,但我仍然无法修复它。

日志:

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
android kotlin android-jetpack-compose compose-recomposition
1个回答
0
投票

FlowRow
似乎不完整,因为
SavedScreen
可组合项隐藏在 TopAppBar 后面。您可能在某些时候使用过
Scaffold
。确保您将脚手架提供的填充应用到
content
:

Scaffold(
    topBar = {
        //...
    },
    content = { innerPadding ->
        Box(
            modifier = Modifier.padding(innerPadding)
        ) {
            //...
        }
    }
)

在我们研究任何重组分析之前:
您正在使用

item
迭代地将新元素添加到单个 LazyColumn
forEach
。这将使 LazyColumn 本身毫无意义,因为它始终只包含一个项目。

我不知道您到底想要实现什么,但如果您想将每个

SavedScreenCard
显示为 LazyColumn 中的单个项目,请考虑按如下方式更新您的代码:

LazyColumn(
    modifier = Modifier.fillMaxSize(),
) {
    savedRecommendationsMap.forEach { (key, value) ->
        if (key.second == true) {
            value?.forEach { recommendation ->
                item {
                    SavedScreenCard(
                        recommendation = recommendation,
                        onClick = onClick,
                        category = key.first,
                    )
                }
            }
        }
    }
}

这将导致正确的 LazyColumn 使用,其中仅组合当前可见的项目(以及其他一些项目),而其他项目在滚动时延迟组合。

© www.soinside.com 2019 - 2024. All rights reserved.