I have a Snackbar which is being opened when a user swipes on a RecyclerView element to delete it. And this Snackbar allows a user to undo his action. I know how to get an element of the RecyclerView back. But I also have a database(SQLite). It seems to me, the best way to do a removal from a detabase is to do it when I understand that a user doesn't press "undo". Otherwise I will need to make a removal and then adding.
I want to do something sort of this:
when (snackbar_button){
was_pressed -> adapter.restoreItem(cachedPosition, cachedItem)
was_not_pressed -> dbManager.removeItem(listArray[pos].id.toString())
}
This is my code on MainActivity:
val onSwipe = object : OnSwipe(this) {
override fun onSwiped(viewHolder: ViewHolder, direction: Int) {
val cachedPosition = viewHolder.absoluteAdapterPosition
val cachedItem = adapter.listArray[cachedPosition]
when (direction) {
ItemTouchHelper.RIGHT -> {
adapter.removeItem(cachedPosition)
Snackbar.make(binding.rv, "Deleted", Snackbar.LENGTH_SHORT)
.apply {
setAction("Undo") {
adapter.restoreItem(cachedPosition, cachedItem)
}
show()
}
}
}
}
}
My adapter:
fun removeItem(pos: Int) {
listArray.removeAt(pos)
notifyItemRemoved(pos)
}
fun restoreItem(pos: Int, listMain: ListItem) {
listArray.add(pos, listMain)
notifyItemInserted(pos)
}
My code in DB to delete:
fun removeItem(_id: String) {
val id = BaseColumns._ID + "=$_id"
Have a look at the
addCallbackfunction - you can add aBaseCallbackwith anonDismissedfunction, where you're provided the reason for the dismissal.DISMISS_EVENT_ACTIONmeans your undo button was clicked, anything else means the snackbar was swiped away, disappeared after a timeout, etc.So you can do something like this:
It would still be a good idea to remove the item from the list though, and restore it in the
setActionlambda or in theonDismissedcallback if the button was pressed. That way the user sees it disappear and reappear - deferring deletion is good for things like avoiding removing things from databases, where you don't want to touch the real data until you're sure.You could still do that with what you have here:
Also if you're going to be accessing the
adapterand managing the undo state externally like this, I'd makeremoveItemreturn the item that was removed (so you don't have to access the adapter's data list directly) and maybe renamerestoreItemtoaddItemsince technically you're inserting whatever you like at a position.Really though, it would be better to keep the last deleted item internal to the adapter, so you can call remove(position) and restore() and let the adapter take care of the details and manage its own state. It's just cleaner and prevents bugs