【问题标题】:How to Bypass Deleting SQLite Data Using Snackbar Undo Action如何使用 Snackbar 撤消操作绕过删除 SQLite 数据
【发布时间】:2016-09-24 06:04:57
【问题描述】:

所以,我正在处理一个项目,我想从 RecyclerView 中删除一个项目,但我希望用户能够通过在 Snackbar 中按“UNDO”来恢复该项目。 RecyclerView 项目正在从 SQLite 数据库中提取它们的数据,当用户删除一个项目时,它会将其从 RecyclerView 以及数据库中我的表的相应行中删除。我的问题是我似乎无法弄清楚如何恢复已删除的数据(SQLite 数据)。

我尝试在我的 DataBaseHelper 类中创建一个方法,该方法将位置作为参数,以便我的光标知道要访问哪一行,然后我使用光标将该行的所有值分配给 AlarmData(我的 setter 和 getter 类) 对象并将其返回给我的适配器类,以便我可以尝试在我的 Snackbar 的 UNDO 操作方法中恢复表的行。

代码如下:

DataBaseHelper.java

// Is public AlarmData even legal? that's my setter and getter class
// and the object type I'm trying to return

   public AlarmData recoverAlarms(int position) {

    AlarmData recoverData = new AlarmData();

    String ALARM_RESTORE_QUERY = "SELECT * FROM " + TABLE_ALARMS + " WHERE " + COLUMN_INDEX +
            " = " + position + ";";

    SQLiteDatabase db = getReadableDatabase();
    Cursor cursor = db.rawQuery(ALARM_RESTORE_QUERY, null);

    try {
        if (cursor.moveToFirst()) {
            do {

                recoverData.set_dispLabel(cursor.getString(cursor.getColumnIndex(COLUMN_LABEL)));
                recoverData.set_dispTime(cursor.getString(cursor.getColumnIndex(COLUMN_TIME)));
                recoverData.set_alarmId(cursor.getInt(cursor.getColumnIndex(COLUMN_INDEX)));

            } while (cursor.moveToNext());
        }
    } catch (Exception e) {
        throw e;
    } finally {
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
            db.close();
        }

    }

    return recoverData;
}

AlarmAdapter.java

   public void deleteAlarm(final int position, final View view) {

    final AlarmData recoverAlarmData = new DataBaseHelper(context, null, null, 1).recoverAlarms(position); //INITIALIZES VARIABLE TO THE OBJECT THAT'S RETURNED
    final AlarmData recoverItem = alarmData.get(position); //Recovers RecyclerView item (this works)
    final DataBaseHelper dataBaseHelper = new DataBaseHelper(context, null, null, 1);


    alarmData.remove(position);
    notifyItemRemoved(position);
    dataBaseHelper.deleteAlarms(position); //DELETES TABLE'S ROW

    Snackbar snackbar = Snackbar.make(view, "Alarm Removed", Snackbar.LENGTH_LONG)
            .setAction("UNDO", new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    alarmData.add(position, recoverItem);
                    notifyItemInserted(position); //RESTORES RECYCLERVIEW ITEM

                    dataBaseHelper.addAlarm(recoverAlarmData); //TRIES TO RECOVER TABLE

                }
            });

    snackbar.show();


}

为了澄清,我想知道如何在我的数据库中复制特定行,以便在用户点击 Snackbar 上的 UNDO 时重新创建它。也可能向我解释我做错了什么。哈哈。。

我希望我在这里没有表现出太多的笨拙。您的帮助将不胜感激。谢谢!

【问题讨论】:

  • 我不知道这通常是如何制作的,但是不删除它呢?在您的表中添加一个active 列,当用户删除您将其设置为“0”(非活动)的字段时,如果他撤消它,您将active 值返回为“1”。在您的回收站视图中,您只显示 active 元素。其他问题是如何在一段时间后删除非活动项目。
  • 您可以只显示 snak bar 并更新回收器视图,但不能真正执行删除方法。让它保持一段时间,直到小吃店消失或使用取消。如果使用命中 undo 将项目插入到 recyclerview 并通知适配器更改。如果小吃店在没有用户交互的情况下消失,则可能在新线程中对数据库进行必要的更改。
  • 您可以在表名中添加一列作为 isDeleted 类型的布尔值。不执行 Hard Delete 应用 Soft Delete 表示不从表中删除项目只需进行 update query 如果用户删除将其设置为 TRUE 否则如果撤消,则为 FALSE。现在您只需要显示未删除的数据。进行查询,只获取 False 标志的数据。
  • 谢谢你们的帮助。我碰巧偶然发现了一个需要很少努力的解决方案。 Lol 显然 Snackbars 有非常方便的回调方法!

标签: android sqlite android-recyclerview undo snackbar


【解决方案1】:

在提问之前我可能应该多花点时间看看。我在这里找到了完美的解决方案:How can I be notified when a Snackbar has dismissed itself?

显然 Snackbars 有很棒的回调方法,你可以重写。这是文档:https://developer.android.com/reference/android/support/design/widget/Snackbar.Callback.html

我只是使用 if 语句来检查 Snackbar 被解雇的原因是什么。我将出于任何原因删除表中的行,除非它的解除是针对操作点击(当用户点击“UNDO”时)。

我的代码:

报警适配器

        Snackbar snackbar = Snackbar.make(view, "Alarm Removed", Snackbar.LENGTH_LONG)
            .setAction("UNDO", new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    alarmData.add(position, recoverItem);
                    notifyItemInserted(position);

                }

            }).setCallback(new Snackbar.Callback() {
                @Override
                public void onDismissed(Snackbar snackbar, int dismissType) {
                    super.onDismissed(snackbar, dismissType);

                    if(dismissType == DISMISS_EVENT_TIMEOUT || dismissType == DISMISS_EVENT_SWIPE
                            || dismissType == DISMISS_EVENT_CONSECUTIVE || dismissType == DISMISS_EVENT_MANUAL)
                    dataBaseHelper.deleteAlarms(position);

                }
            });

【讨论】:

  • 您可以将其简化为if (dismissType != DISMISS_EVENT_ACTION)
  • 工作于 2018 年底。签名已更改并包含一个“事件”int。 1 = 按下撤消,2 = 快餐栏超时
猜你喜欢
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 2012-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多