使用索引引用从 mutableStateListOf 中删除是删除列表中的最后一项,而不是具有相应索引的项

Deleting from a mutableStateListOf using an index reference is deleting the last item in the list and not the item with the corresponding index

提问人:Murphler 提问时间:10/4/2023 最后编辑:Murphler 更新时间:10/5/2023 访问量:41

问:

因此,我希望将 TextField 插图列表添加到屏幕上。该列表是动态的,因此只需单击下面的按钮,用户就可以向屏幕添加新的 TextField。单击后,这些 TextFields 中的信息将循环通过添加到数据库中的信息。没关系,我已经工作了。但是,如果需要,还为用户提供了一个删除图标,用于从屏幕中删除该 TextField。

所以插图是这样的:

data class ContactModel(
    val index : Int = 0,
    val info : ContactInsetModel
)

其中 info 是另一个子数据类,具有

data class ContactInsetModel(
    val index : Int,
    val deleteEntry : (Int) -> Unit,
    val nameEntered : (String) -> Unit,
    val telNoEntered : (String) -> Unit,
)

因此,当单击插图中的删除图标时,它会将索引传递回屏幕以执行删除。在屏幕中的处理方式是问题所在。

@Composable
fun DisplayAddContacts() {

    /** Holds list to be looped and added to DB **/
    val contactEntryList = remember { mutableStateListOf<ContactsEntity>() }

    var name by remember { mutableStateOf("") }
    var number by remember { mutableStateOf("") }
    var uniqueRef by remember {mutableStateOf(0)}

    /** Holds list to be displayed on screen **/
    var insetModelList = remember {
        mutableStateListOf<ContactInsetModel>(
            ContactInsetModel(
                index = uniqueRef,
                deleteEntry = {},
                nameEntered = { name = it },
                telNoEntered = { number = it }
            )
        )
    }

    /** New list in an attempt to map an index to the inset **/
    val listOfEntries =
        insetModelList.mapIndexed { index, info ->
            ContactModel(
                index = index,
                info = info
            )
        }.toMutableList()

                for (i in listOfEntries) {
                    ContactInset().Create(contactModel = i)
                    updateContactsList(i.index, name, number, contactEntryList)
                }

                if (insetModelList.size < 6) {
                        Button(
                            text = "Add another",
                            callback = {
                                ++uniqueRef
                                insetModelList.add(
                                    ContactInsetModel(
                                        index = uniqueRef,
                                        deleteEntry = {

                                        /** THIS IS WHERE THE ISSUES LIE **/

                                        }
                                        nameEntered = { name = it },
                                        telNoEntered = { number = it }
                                    )
                                )
                            }
                        ))
            },
            primaryButton = ButtonModel(
                text = "Save & Continue",
                fillMaxWidth = true,
                callback = {
                    contactEntryList.asReversed().forEach {
                        runBlocking {
                            viewModel.insertContact(
                                ContactsModel(
                                    it
                                )
                            )
                        }
                    }
                }
            ),
        )
}

因此,deleteEntry 回调是问题所在。我尝试过这样的事情

deleteEntry = { index ->
     insetModelList.removeAll{
           it.index == index
     }
}

deleteEntry = { index ->
     insetModelList.removeAt(index)
}

我试过将其过滤到一个新列表

insetModelList = insetModelList.filter { it.index != index }.toMutableStateList()

结果始终是一样的 - 屏幕上的最后一个条目是被删除的条目,而不是选定的条目。在这一点上相当难倒

编辑:所以有人建议我把我的示例代码做得更小一些,所以我试图在下面这样做 - 并提供一些我正在谈论的内容的视觉表示。所以更新了下面的代码示例

@Composable 私人乐趣 DisplayTextFieldList() {

var count = remember { mutableStateOf(0) }
val name = remember { mutableStateOf("") }

val textFieldList = remember { mutableStateListOf<InputFieldModel>() }

/** ADDING FIRST TEXT FIELD TO THE SCREEN **/
if (count.value < 1) {
    textFieldList.add(
        InputFieldModel(
            deleteTextField = {
                textFieldList.removeAt(it)
            },
            name = {
                name.value = it
            }
        )
    )
}

count.value++

/** ADDING INDEX TO DELETE CORRECT ENTRY FROM LIST**/
val listForDisplay = textFieldList.mapIndexed { index, info ->
    InputFieldModelIndexed(
        index = index,
        info = info
    )
}

/** DISPLAYING LIST OF TEXTFIELDS TO SCREEN **/
listForDisplay.forEach {
      BasicTextFieldInset().Create(model = it)
 }
 Button(onClick = {
      /** ADD TEXTFIELD MODEL TO LIST AND SUBSEQUENTLY THE SCREEN**/
      textFieldList.add(
          InputFieldModel(
               deleteTextField = {
               /**  ATTEMPT TO REMOVE TEXTFIELD FROM THE LIST ACCORDING TO ITS INDEX **/
                    textFieldList.removeAt(it)
                },
                 name = {name.value = it}
             )
         )
     }
  ){Text("Add another")},
Button(onClick = {}){Text("Continue")}

}

因此,在我单击“添加另一个”按钮几次后,我最终得到了这样的东西

enter image description here

但是,如果我单击de;ete 图标在“TextField 3”中,我希望看到 test3 消失。相反,test3 仍然存在,并且从列表中删除的是 test5。我不明白为什么会这样

Android Kotlin android-jetpack-compose

评论

0赞 Jorn 10/4/2023
您应该将问题简化为最小的可重现示例。在这样做时,您很可能会自己发现问题。
0赞 Thracian 10/5/2023
您的问题类似于 stackoverflow.com/a/76246080/5457853 的问题。在 mapIndexed 或 foreach 中设置可能会解决此问题key(some unique id) {}

答: 暂无答案