gpt4 book ai didi

android - 滚动时 LazyColumn 不保持项目的状态

转载 作者:行者123 更新时间:2023-12-04 23:38:15 28 4
gpt4 key购买 nike

关注 Pathway谷歌关于 Jetpack compose 的代码实验室,我正在尝试这段代码

import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Divider
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.codelab.basics.ui.BasicsCodelabTheme

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

@Composable
fun MyApp(content: @Composable () -> Unit) {
BasicsCodelabTheme {
Surface(color = Color.Yellow) {
content()
}
}
}

@Composable
fun MyScreenContent(names: List<String> = List(1000) { "Hello Android #$it" }) {
val counterState = remember { mutableStateOf(0) }

Column(modifier = Modifier.fillMaxHeight()) {
NameList(names, Modifier.weight(1f))
Counter(
count = counterState.value,
updateCount = { newCount ->
counterState.value = newCount
}
)
}
}

@Composable
fun NameList(names: List<String>, modifier: Modifier = Modifier) {
LazyColumn(modifier = modifier) {
items(items = names) { name ->
Greeting(name = name)
Divider(color = Color.Black)
}
}
}

@Composable
fun Greeting(name: String) {
var isSelected by remember { mutableStateOf(false) }
val backgroundColor by animateColorAsState(if (isSelected) Color.Red else Color.Transparent)

Text(
text = "Hello $name!",
modifier = Modifier
.padding(24.dp)
.background(color = backgroundColor)
.clickable(onClick = { isSelected = !isSelected })
)
}

@Composable
fun Counter(count: Int, updateCount: (Int) -> Unit) {
Button(
onClick = { updateCount(count + 1) },
colors = ButtonDefaults.buttonColors(
backgroundColor = if (count > 5) Color.Green else Color.White
)
) {
Text("I've been clicked $count times")
}
}

@Preview("MyScreen preview")
@Composable
fun DefaultPreview() {
MyApp {
MyScreenContent()
}
}
我注意到 LazyColumn将在项目变为 时重新组合项目可见在屏幕上(预期行为!)但是, Greeting 的本地状态小部件完全丢失了!
我相信这是 Compose 中的一个错误,理想情况下, Composer 应该考虑 remember缓存状态。有没有一种优雅的方法来解决这个问题?
提前致谢!

最佳答案

[更新]
使用 rememberSaveable {...}赋予在 android 配置更改以及 scrollability 中生存的能力
文档

Remember the value produced by init.
It behaves similarly to remember, but the stored value will survive the activity or process recreation using the saved instance state mechanism (for example it happens when the screen is rotated in the Android application).
现在的代码更优雅更短,我们甚至不需要 吊机状态,它可以保持在内部。我现在唯一不太确定使用 rememberSaveable是当列表越来越大时是否会有任何性能损失,比如 1000 项目。
@Composable
fun Greeting(name: String) {
val isSelected = rememberSaveable { mutableStateOf(false) }
val backgroundColor by animateColorAsState(if (isSelected.value) Color.Red else Color.Transparent)

Text(
text = "Hello $name! selected: ${isSelected.value}",
modifier = Modifier
.padding(24.dp)
.background(color = backgroundColor)
.clickable(onClick = {
isSelected.value = !isSelected.value
})
)
}
[原答案]
基于 @CommonWare的回答 LazyColumn当它们为 时,将处理可组合项及其状态离屏这意味着当 LazyColumn重构 Compsoables再次它将有新的开始 state .要解决此问题,只需发送到 吊机消费者范围内的状态, LazyColumn在这种情况下。
我们还需要使用 mutableStateMapOf()而不是 MutableMapOf里面 remember { ... } lambda 或 Compose-core 引擎将不会意识到此更改。
到目前为止,这里是代码:
@Composable
fun NameList(names: List<String>, modifier: Modifier = Modifier) {

val selectedStates = remember {
mutableStateMapOf<Int, Boolean>().apply {
names.mapIndexed { index, _ ->
index to false
}.toMap().also {
putAll(it)
}
}
}

LazyColumn(modifier = modifier) {
itemsIndexed(items = names) { index, name ->
Greeting(
name = name,
isSelected = selectedStates[index] == true,
onSelected = {
selectedStates[index] = !it
}
)
Divider(color = Color.Black)
}
}
}
快乐作曲!

关于android - 滚动时 LazyColumn 不保持项目的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66516702/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com