2016-05-26 5 views
0

So arbeite ich an einem Projekt, und ich möchte ein Element aus einem RecyclerView löschen, aber ich möchte der Benutzer in der Lage sein, dieses Element durch Drücken von "UNDO" in einem wiederherstellen Imbissbude. Die RecyclerView-Elemente ziehen ihre Daten aus einer SQLite-Datenbank. Wenn der Benutzer ein Element löscht, wird es aus dem RecyclerView und der entsprechenden Zeile meiner Tabelle in der Datenbank entfernt. Mein Problem ist, dass ich nicht herausfinden kann, wie diese gelöschten Daten wiederhergestellt werden können (die SQLite-Daten).So umgehen Sie Löschen von SQLite-Daten mit Snackbar Rückgängig Aktion

Ich habe versucht, eine Methode in meiner DataBaseHelper-Klasse zu machen, die die Position als Parameter übernimmt, so dass mein Cursor weiß, auf welche Zeile zugegriffen werden soll. Dann habe ich den Cursor verwendet, um alle Werte dieser Zeile einem AlarmData (Mein Setter und Getter) zuzuweisen Objekt) und gebe das zurück an meine Adapterklasse, damit ich versuchen kann, die Zeile der Tabelle in der UNDO-Aktionsmethode meiner Snackbar wiederherzustellen.

Hier ist der Code:

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(); 


} 

Gerade clairify, Ich mag gerne wissen, wie ich machen kann eine Kopie einer bestimmten Zeile in meiner Datenbank, damit ich sie neu erstellen kann, wenn der Benutzer auf der Snackbar UNDO drückt. und vielleicht auch erklären, was ich falsch mache. Lol ..

Ich hoffe, dass ich meine Noobishness nicht zu viel hier gezeigt habe. Ihre Hilfe würde sehr geschätzt werden. Vielen Dank!

+0

Ich weiß nicht, wie dies in der Regel gemacht, aber was ist es nicht zu löschen? Fügen Sie eine "aktive" Spalte in Ihrer Tabelle hinzu, wenn der Benutzer das Feld löscht, das Sie als "0" festgelegt haben (nicht aktiv), und wenn er dies rückgängig macht, geben Sie den "aktiven" Wert auf "1" zurück. In Ihrer Recycleransicht zeigen Sie nur die 'aktiven' Elemente an. Eine andere Frage wäre, wie die nicht aktiven Elemente nach einiger Zeit gelöscht werden. –

+0

Sie könnten einfach die Snak-Leiste anzeigen und die Recycler-Ansicht aktualisieren, aber die Löschmethode nicht wirklich ausführen. Halten Sie es für einige Zeit fest, bis die Snackbar verschwindet oder der Gebrauch rückgängig macht. Wenn die Verwendung rückgängig macht, fügen Sie das Element in die Recycleransicht ein und benachrichtigen Sie den Adapter über die Änderungen. Wenn die Imbissleiste ohne Benutzerinteraktion verschwindet, notwendige Änderungen an der Datenbank eventuell in einem neuen Thread vornehmen. –

+0

Entweder Sie können eine Spalte in Ihrem Tabellennamen als isDeleted Typ boolean hinzufügen. Nicht ausführen ** Hard Delete ** anwenden ** Soft Delete ** bedeutet, dass Sie das Element nicht aus der Tabelle löschen, sondern nur eine ** Aktualisierungsabfrage **, wenn der Benutzer löscht, setzen Sie TRUE und andernfalls FALSE, wenn Sie rückgängig machen möchten Zeige nur UN-Gelöschte Daten. eine Abfrage erstellen, die nur die Daten des False-Flags abruft. –

Antwort

1

Ich hätte wahrscheinlich etwas mehr Zeit damit verbringen sollen, zu schauen, bevor ich frage. Ich fand die perfekte Lösung hier: How can I be notified when a Snackbar has dismissed itself?

Anscheinend Snackbars haben tolle Callback-Methoden, die Sie außer Kraft setzen können. Hier ist die Dokumentation: https://developer.android.com/reference/android/support/design/widget/Snackbar.Callback.html

Ich verwende einfach eine if-Anweisung zu überprüfen, was der Grund für die Entlassung der Snackbar war. Ich werde die Zeile in meiner Tabelle aus irgendeinem Grund löschen, außer wenn ihre Ablehnung auf einen Aktionsklick zurückzuführen ist (wenn der Benutzer auf "UNDO" klickt).

Mein Code:

AlarmAdapter

 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); 

       } 
      }); 
+1

Sie könnten das zu 'if (disfidType! = DISMISS_EVENT_ACTION)' vereinfachen. – Sumit