在 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)
就是这样。
我正在使用 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)
就是这样。