android ROOM如何交换两个实体在列表中拖放

68bkxrlz  于 2022-12-31  发布在  Android
关注(0)|答案(3)|浏览(133)

我正在学习如何使用ROOM作为Android架构组件的一部分。对于一个常规的recyclerviews,我可以实现onSwipe来轻松删除列表中的帖子,我的ViewModel将直接调用我的存储库来调用ROOM删除给定的帖子。
然而,当我尝试实现onMove回调时,我遇到了一些问题。回调如下所示:

public boolean onMove(@NonNull RecyclerView recyclerView,
                      @NonNull RecyclerView.ViewHolder viewHolder,
                      @NonNull RecyclerView.ViewHolder target)

从这里我可以得到之前和之后的立场,我天真的想法是,我应该能够交换这两个职位在我的仓库和我的LiveData将自动更新列表。
但是我不知道如何在DAOROOM部件上进行操作(swap)。如果我的方向错了,请分享您的想法或纠正我。

1sbrub3j

1sbrub3j1#

在您的存储库中,您将找到类似以下内容:
第一个月
这可确保Recycler显示器(即LiveData)中的输入与数据库中的任何插入、更新等内容保持一致。
在DAO中,您将看到类似以下内容:

@Query ("SELECT * from record_table ORDER BY id DESC" )
fun getAllRecordssOrderedByIDDesc(): LiveData<List<Record>>

由于拖放后无法修改id,因此需要一个新的数据库列来记录位置。我们将其命名为“position”。您的LiveData现在将是:

var allRecords : LiveData<List<Record>> = fragmentDao.getAllRecordsOrderedByPositionDesc()

基于:

@Query ("SELECT * from record_table ORDER BY position DESC" )
 fun getAllRecordssOrderedByPositionDesc(): LiveData<List<Record>>

一旦新位置记录在数据库中,它将是永久性的,即您可以停止应用程序,重新启动它,记录仍将显示在新位置(LiveData使用从数据库读取的位置,如上所述)。
另一种方法是使用首选项来记录拖放更改。数据库加载后,这些更改将被应用。有赞成也有反对。更新数据库中的位置可以通过数据库更新来完成,在reoverride fun clearView中调用recyclerView.adapter.notifyItemMoved(from,to)(在override fun onMove中)。
您需要代码来确定新的位置。它比"位置3的项转到位置5“更复杂。例如,将适配器位置3的项拖动到位置10意味着以下更改:

3 -> null
4 -> 3
5 -> 4
...

9 -> 8
10 -> 9
and finally 3 -> 10

java.util、Collections.swap可用于:

from = viewHolder.adapterPosition
to = target.adapterPosition
Collections.swap(mutableList, from, to)

in override fun onMove(...)然后可以使用mutableList来驱动数据库位置更新。

lg40wkob

lg40wkob2#

For drag and swipe in recyclerview follow this url
但是,如果你想保持新的顺序列表.

  • 保持表格中的位置,如1、2、3......。
  • 使用房间查询获取列表-使用位置排序项目
  • 用户拖放,更新数据库中的新位置
  • 要获取位置=〉查看者.getAdapterPosition(),目标.getAdapterPosition()
  • 当数据库发生变化时,将触发Livedata,您将从数据库中获得新列表。
hc8w905p

hc8w905p3#

关于排序的问题。当拖放项目时,实体中的每一个数据都需要在正确的位置,我想我有完美的解决方案。
顺便说一句,我的答案是基于@NY-Newboid,它通过添加一个新的列部分来定位实体中每个数据的位置。
顺便说一句,我在利用Kotlin.
When item is dragged....
当项目被拖动时,如下图所示,fun onMove将被调用两次。每次调用时,只有2个项目会受到影响。因此,我们可以在每次onMove调用时使用@update fun update(item1 : Entity,item2 : Entity)。在项目2的位置之间切换,实体中的数据会像爬楼梯一样逐个重新排列。最终将在用户放下该项目时停止执行此操作。
这是我在Note数据库项目上的代码,
在注解数据类中

@Entity(tableName = "note_table")data class Note(
@PrimaryKey(autoGenerate = true)
var id: Int,
val title: String,
val description: String,
val position: Int


在DAO中

@Update
suspend fun update(note1: Note, note2: Note)

在活动主页中

override fun onMove(
            recyclerView: RecyclerView,
            viewHolder: RecyclerView.ViewHolder,
            target: RecyclerView.ViewHolder
        ): Boolean {

            val fromPosition = viewHolder.adapterPosition //started position
            val toPosition = target.adapterPosition //ended position

            val oriNote1 = noteAdapter.getNote(fromPosition) //note that are dragged
            val oriNote2 = noteAdapter.getNote(toPosition) //note that are affected
            val newNote1 = Note(oriNote1.id,oriNote1.title,oriNote1.description,toPosition)
            val newNote2 = Note(oriNote2.id,oriNote2.title,oriNote2.description,fromPosition)
            noteAdapter.isItemMoved() //setting up boiler code to disable notifyDataSetChanged()
            noteViewModel.update(newNote1,newNote2)
            noteAdapter.notifyItemMoved(fromPosition,toPosition)
            return true
        }

在循环视图适配器类中,

private var notes: List<Note> = ArrayList()
private var isItemMoved: Boolean = false

fun setNote(notes: List<Note>) {
    this.notes = notes
    println(isItemMoved)
    if (!isItemMoved) {
        notifyDataSetChanged()
    }
    isItemMoved = false
}

fun isItemMoved(){
    println("set it to true")
    isItemMoved = true
}

希望这能帮上忙

相关问题