Home > database >  Recyclerview list item vanishes after closing and restarting app. KOTLIN
Recyclerview list item vanishes after closing and restarting app. KOTLIN

Time:10-06

I just implemented an undo function for a snackbar in my to do list app. Everything works perfectly until you close the app and open it again. Once it's opened the list item that was just restored/undone does not show up. However if you exit the app and NOT close it. The list item is still there.

override fun onViewSwiped(position: Int) {

    val removedItem = list.removeAt(position)
    notifyItemRemoved(position)
    updateNotesPositionInDb()

    val snackBar = Snackbar
        .make((context as Activity).findViewById(R.id.mainLayout), "Task deleted", Snackbar.LENGTH_LONG)
        .setAction("Undo"){

            undoDeleteTask(removedItem.ID)
            list.add(position, removedItem)
            notifyItemInserted(position)
            updateNotesPositionInDb()

        }
        .addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
            override fun onShown(transientBottomBar: Snackbar?) {

            }

            override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                deleteTask(removedItem.ID)
                updateNotesPositionInDb()
            }
        })
    snackBar.show()
}
fun undoDeleteTask(id: String) {

    val db = mHelper.readableDatabase
    db.insert(TaskContract.TaskEntry.TABLE, "id=$id", null)
    db.close()

}

Let me explain again. When a user swipes the item and they press undo. The item will be added back to the recyclerview. If a user were to exit the app, but not close it. The item will store be there. However if the user were to close the app then open it, the recently restored item is no longer there.

CodePudding user response:

Your Snackbar callback always deletes the item from the database

override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
    deleteTask(removedItem.ID)
    updateNotesPositionInDb()
}

From the docs:

public void onDismissed (B transientBottomBar, int event)

Called when the given BaseTransientBottomBar has been dismissed, either through a time-out, having been manually dismissed, or an action being clicked.

So even if the user clicks that undo action, the dismissed callback runs and always deletes from the DB. You need to check that event parameter in the callback, and make sure it doesn't do the delete operation if it was a click that dismissed it:

int: The event which caused the dismissal. One of either: DISMISS_EVENT_SWIPE, DISMISS_EVENT_ACTION, DISMISS_EVENT_TIMEOUT, DISMISS_EVENT_MANUAL or DISMISS_EVENT_CONSECUTIVE.

I'm guessing just an if (event != DISMISS_EVENT_ACTION) will do it!


The reason you're only seeing this on a restart is that I'm guessing deleteTask(removedItem.ID) doesn't update your in-memory list or the RecyclerView's adapter - your flow here seems to be

  • remove from the in-memory list
  • if the user clicks undo then restore it
  • if they don't then remove it from the DB as well

So what happens here is it's removed from the in-memory list, then it's restored, then the data is removed from the DB. So long as the app stays in memory you'll be able to see the data that's in the list. But as soon as you restart the app, it has to restore the list by reading the DB, and the item isn't in there anymore

  • Related