Reputation: 163
I use in project RecyclerView
, Room DB
and trying to make a function to add a record to table or remove if exists by clicking button. But the main problem is that function executes infinitely (adds, removes and again).
Here is code:
Fragment
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)
Repository
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)
}
And 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>
Upvotes: 0
Views: 101
Reputation: 97
Well, you don't need to check whether it's in a database or not. just pass CoverId in deleteCover Method and run query. but still, if you have a case to check then below is the way. You don't need live data call
Your DAO would be like
@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 would be
suspend fun deleteCover(id: String) = db.coversDao().deleteCover(id)
fun checkCoverInDb(textId: String) : Cover? {
return db.coversDao().checkCover(textId = textId)
}
and your method would be like
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()
}
}
Upvotes: 1
Reputation: 1702
If the function executes infinitely before click the button ,move the observer code into onclick().
Upvotes: 0
Reputation: 7642
You probably don't need a reactive pattern, liveData
for your saveDeleteCover
function. Currently why you get an infinite save/remote operation is because:
null
cover
cover
cover
Then the steps get repeated from step 1.
I suspect you're trying to favorite/unfavorite an item based on a click, so you could just simply call:
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()
}
}
That way your operation will run only on the latest value
Upvotes: 0