Android 房间:无限添加和删除作品

Android Room: Adding and removing works infinitely

我在项目 RecyclerViewRoom DB 中使用,并尝试创建一个函数以将记录添加到 table 或通过单击按钮删除(如果存在)。但主要问题是函数会无限执行(添加、删除并再次执行)。

代码如下:

片段

override fun saveDeleteCover(image: ImageView, cover: Cover) {
    viewModel.checkIfCoverInDatabase(cover).observe(viewLifecycleOwner, { savedCover ->
        //If savedCover is null then save item to table. Otherwise remove
        if(savedCover == null) {
            viewModel.saveCover(cover)
            Toast.makeText(context, "Added to favorite", Toast.LENGTH_SHORT).show()
        } else {
            viewModel.deleteCover(cover)
        Toast.makeText(context, "Removed from favorite", Toast.LENGTH_SHORT).show()
        }
    })
}

ViewModel

fun saveCover(cover: Cover) = viewModelScope.launch {
    coverRepository.upsert(cover)
}

fun deleteCover(cover: Cover) = viewModelScope.launch {
   coverRepository.deleteCover(cover)
}

fun checkIfCoverInDatabase(cover : Cover) = coverRepository.checkCoverInDb(cover.textId)

存储库

suspend fun upsert(cover : Cover) = db.coversDao().upsert(cover)

suspend fun deleteCover(cover: Cover) = db.coversDao().deleteCover(cover)

fun checkCoverInDb(textId: String) : LiveData<Cover> {
    return db.coversDao().checkCover(textId = textId)
}

和DAO

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun upsert(cover : Cover) : Long

@Delete
suspend fun deleteCover(cover: Cover)

@Query("SELECT * FROM covers WHERE textId=:textId")
fun checkCover(textId: String) : LiveData<Cover>

您的 saveDeleteCover 函数可能不需要反应模式,liveData。目前你得到无限 save/remote 操作的原因是:

  1. 检查数据库发出新值 - null
  2. 您保存 cover
  3. 再次触发检查数据库,并发出新的 - cover
  4. 你删除cover

然后从第 1 步开始重复这些步骤。

我怀疑您正在尝试 favorite/unfavorite 基于点击的项目,因此您只需调用:

override fun saveDeleteCover(image: ImageView, cover: Cover) {
        if(viewModel.checkIfCoverInDatabase(cover).value == null) {
            viewModel.saveCover(cover)
            Toast.makeText(context, "Added to favorite", Toast.LENGTH_SHORT).show()
        } else {
            viewModel.deleteCover(cover)
        Toast.makeText(context, "Removed from favorite", Toast.LENGTH_SHORT).show()
        }
}

这样您的操作将 运行 仅针对最新值

如果函数在点击按钮之前无限执行,将观察者代码移到 onclick() 中。

好吧,您不需要检查它是否在数据库中。只需在 deleteCover 方法中传递 CoverId 和 运行 查询即可。但是,如果您有案例要检查,那么下面就是方法。您不需要实时数据通话

你的 DAO 会像

@Query("SELECT * FROM covers WHERE textId=:textId")
fun checkCover(textId: String) : Cover?

@Query("DELETE FROM covers WHERE textId=:Id")
suspend fun deleteCover(Id: String)

REPO 将是

suspend fun deleteCover(id: String) = db.coversDao().deleteCover(id)
fun checkCoverInDb(textId: String) : Cover? {
      return db.coversDao().checkCover(textId = textId)
}

你的方法就像

override fun saveDeleteCover(image: ImageView, cover: Cover) {
 val cover =  viewModel.checkCoverInDb(cover.textId)
 if(cover == null) {
        viewModel.saveCover(cover)
        Toast.makeText(context, "Added to favorite", Toast.LENGTH_SHORT).show()
    } else {
        viewModel.deleteCover(cover.textId)
    Toast.makeText(context, "Removed from favorite", Toast.LENGTH_SHORT).show()
    }
 }