我有一個使用 布局的 Todo 串列LazyColumn,每個專案都是另一個CardView處理每個 TodoModel 的 Composable ()。我正在使用rememberSaveable來管理這個 CardView 自己的可組合的狀態(例如 TextField、可點擊的影像等),以便在方向變化時也能幸免于難。
我已經學會了使用LazyList's 鍵來告訴結構每個專案都是唯一的,在這種情況下,我使用的是模型的 id。
這個 todolist 的作業方式是它的單個螢屏顯示已保存的 todo 串列(通過房間持久保存),以及一個簡單的 FAB 按鈕,單擊該按鈕時,它會添加一個臨時 todo 項(具有 id 的新 todo 模型-1L) 在串列中(它將顯示在螢屏中待辦事項的頂部),這是用戶可以編輯待辦事項的標題和內容的地方。總而言之,您可以在單個螢屏中洗掉/編輯/創建新的 Todo,所有保存的 Todo 都有正 ID,對于新的,我總是將其設定為 -1。保存后,新 todo 模型的 id 為 -1L 將在整個螢屏的視圖模型(DashboardScreen's ViewModel)中提升的串列(由 Room 回傳的 id)中修改
我注意到的是當我以這種方式在惰性串列中定義一個鍵時(LazyDSL)
LazyColumn {
items(key = { it.id },items = todoList) { todo ->
TodoCardItem(
todoModel = todo,
...,
...
并通過以下一系列動作
- 點擊 Fab, New todo (id of
-1L), 空標題 - 保存這個新的Todo(保存后,id會被修改為正數),title = "My First Todo"
- 點擊Fab,New Todo(id of
-1L),title不為空,顯示=“My First Todo”
它參考了卡的舊狀態。
但是當我以這種方式定義鍵時(可組合鍵)
LazyColumn {
items(items = todoList) { todo ->
key (todo.id) {
TodoCardItem(
todoModel = todo,
...,
...
它按我的預期作業,每一個新的待辦事項都是完全干凈的,它還能在旋轉等配置更改中幸存下來(盡管當我最小化應用程式時我崩潰了,這是我需要稍后處理的事情)。
對于rememberSaveable,它被初始化為TodoModel
.....
companion object {
val Saver = Saver<TodoItemState, Map<String, Any>>(
save = { instanceOfOriginal ->
mapOf(
KEY_MODEL to instanceOfOriginal.todoModel,
KEY_TITLE to instanceOfOriginal.title
)
},
restore = { restorer ->
val state = TodoItemState(restorer[KEY_MODEL] as TodoModel)
state.title = restorer[KEY_TITLE] as String
state
}
)
private const val KEY_MODEL = "key_model"
private const val KEY_TITLE = "key_title"
}
}
@Composable
internal fun rememberTodoItemState(todoModel: TodoModel) =
rememberSaveable(
saver = TodoItemState.Saver
) {
TodoItemState(todoModel)
}
這是一個很大的代碼,所以如果對它的某些部分有進一步的擔憂,比如顯示視圖模型代碼,模型的 id 是如何修改的,我會在進一步的問題上粘貼它。
uj5u.com熱心網友回復:
通過做這個:
items(items = todoList) { todo ->
key (todo.id) {
您不僅要重置-1L視圖,還要重置插入的單元格下方的所有其他單元格。
當你不指定key時,默認情況下它等于單元格索引,所以在另一個里面有兩個鍵,當索引移動時,所有內部鍵都變得無效并且必須創建一個新視圖。您可以通過LaunchedEffect在key.
我認為最正確的方法是為每個新專案創建一個唯一鍵,并存盤一個帶有新專案 ID 的地圖:這將確保 tmp 單元格與新內容一起重用。
private val newItemIdsMap = mutableMapOf<Long, Long>()
fun addTmpItem() {
var tmpId: Long
do {
tmpId = Random.nextLong(Long.MIN_VALUE, -1)
} while (newItemIdsMap.containsValue(tmpId))
val tmpItem = Item(id = tmpId)
items.add(0, tmpItem)
}
fun saveItem(tmpItem: Item) {
val savedItem = saveToDb(tmpItem)
newItemIdsMap[savedItem.id] = tmpItem.id
items[0] = savedItem
}
fun getItemId(item: Item) : Long {
val savedId = newItemIdsMap[item.id]
return savedId ?: item.id
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/486469.html
標籤:科特林 android-jetpack-compose 懒人列
上一篇:Kotlin中二叉樹的深度
