#android #kotlin #android-jetpack-compose
Вопрос:
Я пробовал сочинять Jetpack и наткнулся на что-то со 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 строк, где в каждой строке написано «Привет, Пуфи #N», за которым следует кнопка с надписью «Нажал N раз».
Все это работает нормально, но если я нажму кнопку, чтобы обновить ее количество, это количество не сохранится при прокрутке за кадром и включении обратно.
LazyColumn
«Переработка» перекомпилирует строку и счетчик. В приведенном выше примере счетчик поднят вверх, NameList()
но я попробовал его самостоятельно Counter()
. Ни то, ни другое не работает.
Как правильно помнить графа? Должен ли я хранить его в массиве в действии или что-то в этом роде?
Ответ №1:
Представления для items
повторно используются, и с новым index
значением значение remember
сбрасывается. Это ожидаемое поведение, и вы не должны ожидать, что это значение сохранится.
Вам не нужно держать его в действии, вам просто нужно убрать его из 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
вместо хранения данных внутри модели представления.
Подробнее о состоянии в Compose читайте в документации