在 RecyclerView 中移动项目会使视图中的项目加倍

Moving item in RecyclerView doubles item in view

我正在使用 RecyclerView 在消息传递应用程序中构建联系人列表 (ArrayList)。

当联系人更新时,我想将该用户移到列表顶部,而列表中的所有其他项目都向下移动一级。

我正在使用 Firestore 获取用户列表。

DocumentChange.Type.MODIFIED -> {
                        val matchThatChanged = dc.newIndex
                        
                        matchesArrayList[matchThatChanged] = ChatMatchListMatch(
                            matchUserID)

                        adapter.notifyItemChanged(matchThatChanged) //Ensures change is visible immediately

                        val fromPosition = matchesArrayList.indexOfFirst {
                            it!!.matchUserID == matchUserID
                        }

                        
                        Log.d(TAG, "From position A: $matchThatChanged")

                        if (fromPosition != 0) {
                            adapter.moveMatchToTop(
                                fromPosition, ChatMatchListMatch(
                                    matchUserID
                                )
                            )
                        }
                    }

在此处的日志中,当我迈出第一步时,它正确地输出了 1。但是,此后当我尝试更新其他用户时它输出 0?这是不正确的。被下推的用户不应再为 0,而应为 1。因为现在错误地为 0,所以它不是 运行 代码(这不是问题。问题是应该首先不是 0)。

这是我的适配器中的代码:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val view: View = LayoutInflater.from(parent.context)
        .inflate(R.layout.chat_matchlist_item, parent, false)
    return CustomViewHolder(view)
}

// Passes the ContactListMatch object to a ViewHolder so that the contents can be bound to UI.
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    val contactListMatch = mMatchesArrayList[position]
    (holder as CustomViewHolder).bind(contactListMatch)
}

fun moveMatchToTop(fromPosition: Int, chatMatchListMatch: ChatMatchListMatch) {
    mMatchesArrayList.removeAt(fromPosition)
    notifyItemChanged(fromPosition)
    notifyItemRemoved(fromPosition)
    mMatchesArrayList.add(0, chatMatchListMatch)
    notifyItemInserted(0)
    notifyItemChanged(0)
    notifyItemChanged(1)
   
}

我要开始的清单是:

当我只更新底部用户 (2) 时,它显示正确(将用户二移至顶部,将另一个用户移至下方):

我现在尝试再次更新原始用户 1,我希望它再次位于顶部,如下所示:

但我得到的是:

我想出了解决办法。我不得不做出几处更改,但我会尽力帮助可能遇到类似问题的其他人:

我在 Firestore 中使用了一个索引,并使用了两个“orderby”查询来按照我想要的顺序获取列表:

myCollectionRef
        .orderBy("unread", Query.Direction.DESCENDING)
        .orderBy("timeStamp", Query.Direction.DESCENDING)
        .addSnapshotListener

然后根据情况修改:

DocumentChange.Type.MODIFIED -> {

我不得不获取旧索引,并且更改了项目的新索引。当我得到旧索引时(通过遍历我的列表以使用 for 循环查找它),我确保从列表中删除该项目并通知我的适配器我删除了该项目:

val newIndex = dc.newIndex

var oldIndex = -1
for (i in myList.indices.reversed()) {
     if (myList[i]!!.IDnumber == userID) {
          oldIndex = i                                                                   
          myList.removeAt(oldIndex)
          adapter.notifyItemRemoved(oldIndex)
          }
     }

然后我必须将更改的项目添加回列表中的正确位置。由于我有新索引,这很容易。我还将更改通知我的适配器:

myList.add(
     newIndex, MySpecialItem(
          userID!!,
          userImageOrWhatever!!
          )
     )
                        
 adapter.notifyItemInserted(newIndex)

就是这样。