LazyColumn 中每个项目的状态提升

Posted

技术标签:

【中文标题】LazyColumn 中每个项目的状态提升【英文标题】:State hoisting for each item in LazyColumn 【发布时间】:2021-09-28 02:30:40 【问题描述】:

我已经通过this codelab。在第 7 步中,当单击单行文本时,它会改变它的颜色,但函数不会跟踪它,这意味着它会在重新组合后消失。

我希望列表记住单个项目的颜色,因此我将状态提升移至 NameList 函数级别。 不幸的是,它不起作用。

错误在哪里?

    @Composable
fun NameList(names: List<String>, modifier: Modifier = Modifier) 

    LazyColumn(modifier = modifier) 
        items(items = names)  name, ->
            val isSelected  = remember  mutableStateOf(false)
            Greeting(name = name,isSelected.value) newSelected -> isSelected.value = newSelected
            Divider(color = Color.Black)
        
    


@Composable
fun Greeting(name: String,isSelected : Boolean, updateSelected : (Boolean) -> Unit) 

    val backgroundColor by animateColorAsState(if (isSelected) Color.Red else Color.Transparent)
    Text(
        modifier = Modifier
            .padding(24.dp)
            .background(color = backgroundColor)
            .clickable(onClick =  updateSelected(!isSelected)),
        text = "Hello $name",

        )

【问题讨论】:

【参考方案1】:

你应该将你的选择状态提升到NameList函数的调用者。

@Composable
fun MyScreen() 
    // Fake list of names
    val namesList = (1..100).map  "Item $it" 
    // Here, we're keeping the selected positions. 
    // At the beginning, all names are not selected.
    val selection = remember 
        mutableStateListOf(*namesList.map  false .toTypedArray())
    
    
    NameList(
        // list of names
        names = namesList, 
        // list of selected items
        selectedItems = selection,
        // this function will update the list above
        onSelected =  index, selected -> selection[index] = selected ,
        // just to occupy the whole screen 
        modifier = Modifier.fillMaxSize()
    )

然后,您的NameList 将如下所示:

@Composable
fun NameList(
    names: List<String>,
    selectedItems: List<Boolean>,
    onSelected: (index: Int, selected: Boolean) -> Unit,
    modifier: Modifier = Modifier
) 
    LazyColumn(modifier = modifier) 
        itemsIndexed(items = names)  index, name ->
            Greeting(
                name = name, 
                isSelected = selectedItems[index],
                updateSelected =  onSelected(index, it) 
            )
            Divider(color = Color.Black)
        
    

Greeting 函数没有任何变化。

结果如下:

【讨论】:

以上是关于LazyColumn 中每个项目的状态提升的主要内容,如果未能解决你的问题,请参考以下文章

LazyColumn 项目互斥

在 React 中提升状态不会导致不必要的重新渲染吗?

Jetpack Compose - 恢复 LazyColumn 滚动状态

Kotlin Compose Todo小项目 删除添加项目 ,认识状态提升

卡中带有标题项目和卡中剩余项目的 LazyColumn

经过一顿骚操作,项目编译打包速度提升一倍!