Всегда ли Compose запоминает старый элемент на основе идентификатора, даже если список был обновлен до более нового?
У меня есть простой пример приложения, которое может
- Загрузить новый список (из 2 элементов, с идентификаторами 0 и 1 и случайным текстом для каждого)
- Он может провести пальцем, чтобы закрыть любой элемент.
Если я
- загрузить новый список в первый раз
- проведите пальцем, чтобы удалить первый элемент
- загрузить новый список (с тем же идентификатором, но другим случайным текстом)
- проведите пальцем, чтобы удалить второй элемент
Он выйдет из строя, как показано на GIF ниже (вы можете получить дизайн кода здесь https://github.com/elye/issue_android_jetpack_compose_swipe_to_dismiss_ Different_data_same_id)
Причина в сбое, потому что при пролистывании для отклонения 2-го элемента (из данных, загруженных во второй раз) найденный элемент по-прежнему является 2-м элементом данных, загруженных в первый раз.
Кажется, что rejectState (как показано ниже) всегда помнит данные, загруженные в первый раз (вместо новых загруженных данных)
val dismissState = rememberDismissState(
confirmStateChange = {
Log.d("Track", "$item\n${myListState.value.toMutableList()}")
viewModel.removeItem(item)
true
}
)
Следовательно, это приводит к тому, что при удалении отправляется неправильный элемент для удаления, что приводит к сбою и сбою.
Полный код LazyColumn и SwipeToDismiss показан ниже.
LazyColumn(modifier = Modifier.fillMaxHeight()) {
items(
items = myListState.value,
key = { todoItem -> todoItem.id }
) { item ->
val dismissState = rememberDismissState(
confirmStateChange = {
viewModel.removeItem(item)
true
}
)
SwipeToDismiss(
state = dismissState,
background = {
dismissState.dismissDirection ?: return@SwipeToDismiss
Box(modifier = Modifier.fillMaxSize().background(Color.Red))
},
dismissContent = {
// The row view of each item
}
)
}
}
Это
- Моя проблема в том, что я упускаю что-либо, чтобы обновить отклонение состояния при загрузке новых данных?
- Ошибка Google, из-за которой SwipeToDismiss всегда должен работать со списком уникальных идентификаторов. Даже если список обновляется до нового списка, он не может иметь тот же идентификатор, который совпадает с любым элементом предыдущего списка.
- то есть если я заменю
key = { todoItem -> todoItem.id }
сkey = { todoItem -> todoItem.title }
, тогда все будет хорошо
- то есть если я заменю
1 ответ
rememberDismissState()
будет помнитьconfirmStateChange
лямбда, которая является частьюDismissState
. В вашем случае может измениться, но лямбда фиксирует только начальнуюitem
значение, приводящее к сбою.
Вы можете использоватьrememberUpdatedState
чтобы решить это:
val currentItem by rememberUpdatedState(item)
val dismissState = rememberDismissState(
confirmStateChange = {
viewModel.removeItem(currentItem)
true
}
)