【问题标题】:Jetpack Compose LazyColumn recomposition with remember()Jetpack Compose LazyColumn 使用 remember() 重构
【发布时间】:2021-10-15 21:32:55
【问题描述】:

我一直在尝试 Jetpack Compose,但遇到了 LazyColumn 列表和 remember() 的问题。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApp{
                MyScreen()
            }
        }
    }
}

@Composable
fun MyApp(content: @Composable () -> Unit){
    ComposeTestTheme {
        // A surface container using the 'background' color from the theme
        Surface(color = MaterialTheme.colors.background) {
            content()
        }
    }
}

@Composable
fun MyScreen( names: List<String> = List(1000) {"Poofy #$it"}) {
    NameList( names, Modifier.fillMaxHeight())
}

@Composable
fun NameList( names: List<String>, modifier: Modifier = Modifier ){
    LazyColumn( modifier = modifier ){
        items( items = names ) { name ->
            val counter = remember{ mutableStateOf(0) }

            Row(){
                Text(text = "Hello $name")
                Counter(
                    count = counter.value,
                    updateCount = { newCount -> counter.value = newCount } )
            }
            Divider(color = Color.Black)
        }
    }
}

@Composable
fun Counter(count: Int, updateCount: (Int) -> Unit) {
    Button( onClick = {updateCount(count+1)} ){
        Text("Clicked $count times")
    }
}

这会运行并创建一个包含 1000 行的列表,其中每行显示“Hello Poofy #N”,然后是一个显示“Clicked N 次”的按钮。

一切正常,但如果我点击一个按钮来更新它的计数,当它滚出屏幕并重新打开时,计数将不会持续存在。

LazyColumn“回收”重新组合了行和计数。在上面的示例中,计数器被提升到NameList(),但我已经尝试在Counter() 中未提升它。两者都不起作用。

记住计数的正确方法是什么?我必须将它存储在活动中的数组中吗?

【问题讨论】:

    标签: android kotlin android-jetpack-compose


    【解决方案1】:

    items 的表示被回收,并且使用新的indexremember 的值被重置。这是预期的行为,您不应期望此值会持续存在。

    您无需将其保留在活动中,只需将其移出LazyColumn。例如,您可以将其存储在可变状态列表中,如下所示:

    val counters = remember { names.map { 0 }.toMutableStateList() }
    LazyColumn( modifier = modifier ){
        itemsIndexed(items = names) { i, name ->
            Row(){
                Text(text = "Hello $name")
                Counter(
                    count = counters[i],
                    updateCount = { newCount -> counters[i] = newCount } )
            }
            Divider(color = Color.Black)
        }
    }
    

    或者在可变状态映射中:

    val counters = remember { mutableStateMapOf<Int, Int>() }
    LazyColumn( modifier = modifier ){
        itemsIndexed(items = names) { i, name ->
            Row(){
                Text(text = "Hello $name")
                Counter(
                    count = counters[i] ?: 0,
                    updateCount = { newCount -> counters[i] = newCount } )
            }
            Divider(color = Color.Black)
        }
    }
    

    请注意remember 也会在屏幕旋转时重置,请考虑使用rememberSaveable 而不是将数据存储在视图模型中。

    documentation 中阅读有关 Compose 中状态的更多信息

    【讨论】:

      猜你喜欢
      • 2021-06-01
      • 2022-07-29
      • 1970-01-01
      • 2022-11-10
      • 2022-08-22
      • 2022-09-26
      • 1970-01-01
      • 2022-10-04
      • 1970-01-01
      相关资源
      最近更新 更多