Kurz gesagt, Sie müssen in der Lage sein, eine zu löschende Zeile anhand der für die ListView verfügbaren Daten zu unterscheiden. Wenn der Wert vom Cursor abgerufen wird, als zweite Spalte (d. h. der String, der mit res.getString(1))
extrahiert wurde , und der Wert wird eindeutig sein , können Sie diese abrufen und für die Löschung verwenden.
Es gibt jedoch einige Probleme bei der Verwendung eines ListAdapter
wird wohl nicht reichen. Es gibt andere Adapter, wie z. B. einen ArrayAdapter, der mehr Funktionen bietet, und vor allem ein notifyDatasetChanged
-Methode (die die zugehörige ListView aktualisiert).
Es ist eine Verschwendung, für jede Iteration des Cursors einen neuen Adapter zu erstellen. Der Adapter sollte also außerhalb der Schleife und nur einmal erstellt werden.
Ich würde vorschlagen, dass das Löschen auf Elementklick zu anfällig für versehentliches Klicken ist, das Löschen auf Element LongClick wäre weitaus weniger anfällig für versehentliches Löschen.
Wenn Sie Variablen in Klassenvariablen verschieben, müssen Sie sie nicht als endgültig deklarieren.
Basierend auf dem oben Gesagten könnten Sie also Folgendes haben:-
Array-Adapter-Methode
public class ZeigeFaecherListe extends AppCompatActivity {
DatabaseHelper myDb;
Cursor res;
ListView listViewFaecher;
ArrayAdapter<String> fachListAdapter;
ArrayList<String> faecherListe;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.zeige_faecher);
listViewFaecher = (ListView) this.findViewById(R.id.listview);
myDb = new DatabaseHelper(this);
addSomeData(); //<<<<<<<<<< ADDED for testing
faecherListe = new ArrayList<>();
res = myDb.zeigeFaecher();
while (res.moveToNext()) {
faecherListe.add(res.getString(1));
}
//<<<< NOTE outside of the loop as this only needs to be done once
fachListAdapter = new ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
faecherListe
);
listViewFaecher.setAdapter(fachListAdapter);
//<<<<< NOTE used LONG CLICK listener (less likely to accidentally delete)
listViewFaecher.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
myDb.deleteRow((String)fachListAdapter.getItem(position));
faecherListe.remove(position);
fachListAdapter.notifyDataSetChanged();
return true; //<<<< Indicate that this longclick has been used
}
});
}
private void addSomeData() {
for (int i=1; i <= 10; i++) {
myDb.addRow("Row " + String.valueOf(i));
}
}
}
Zusammen mit dem obigen deletRow
Methode ist:-
public int deleteRow(String col2) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
- wo
- TB001 ist ein konstanter String, der auf den Namen der Tabelle gesetzt wird.
- COL_TB001_DATA ist der Spaltenname der 2. Spalte.
WARNUNG Die obige Lösung funktioniert nur dann korrekt, wenn die 2. Spalte eindeutige Daten enthält, da sonst mehrere Zeilen gelöscht würden.
Es gibt auch die Annahme, dass das Löschen funktioniert, es könnte besser sein, :-
zu haben @Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (myDb.deleteRow((String)fachListAdapter.getItem(position))<0) {
faecherListe.remove(position);
}
fachListAdapter.notifyDataSetChanged();
return true; //<<<< Indicate that this longclick has been used
}
Cursor-Adapter-Methode
Es gibt jedoch andere für Cursor geeignete Adapter, die die Notwendigkeit eines Zwischenarrays überflüssig machen könnten. Sie könnten einen CursorAdapter
verwenden . Für einen CursorAdapter
ein Spaltenname _id
ist erforderlich und diese Spalte sollte lang sein und auch eindeutig die Zeile identifizieren. Die Absicht und daher der Name ist, dass ein Alias der rowid verwendet wird (daher auch die Konstante BaseColumns._ID
existiert).
Ein Alias der rowid wird durch die Definition von ?? INTEGER PRIMARY KEY
wo ?? ist der Spaltenname. Idealerweise sollte die Tabelle also inklusive einer Spaltendefinition mit _id INTEGER PRIMARY KEY
definiert werden z.B. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT)
(Sie können INTEGER PRIMARY KEY
folgen mit dem Schlüsselwort AUTOINCREMENT, aber im Allgemeinen würden Sie dies nicht tun, da es Overheads von SQLite Autoincrement hat)
Wenn Ihre Tabelle keine solche Spalte hat, können Sie beim Abfragen der Daten immer eine Spalte im Cursor erstellen, indem Sie rowid AS _id
verwenden z.B. wenn Sie SQL mit SELECT * FROM mytable
gleichsetzen dann können Sie SELECT *, rowid AS _id FROM mytable
verwenden .
In diesem Beispiel der vorrätige SimpleCursorAdapter
verwendet wird, könnte der Code :-
public class ZeigeFaecherListe extends AppCompatActivity {
DatabaseHelper myDb;
Cursor res;
ListView listViewFaecher;
SimpleCursorAdapter fachSimpleCursorAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.zeige_faecher);
listViewFaecher = (ListView) this.findViewById(R.id.listview);
myDb = new DatabaseHelper(this);
addSomeData(); //<<<<<<<<<< ADDED for testing
faecherListe = new ArrayList<>();
res = myDb.zeigeFaecher();
fachSimpleCursorAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, //<<<< The layout
res, //<<<< The Cursor
new String[]{"_data"}, //<<<< The column names from which to get the data
new int[]{android.R.id.text1} //<<<< The ids of the views in which the data is placed
);
listViewFaecher.setAdapter(fachSimpleCursorAdapter);
listViewFaecher.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// id is the value of the respective _id column
//<<<< Normally you would have the delete method in the Databasehelper >>>>
myDb.getWritableDatabase().delete("mytable","_id=?",new String[]{String.valueOf(id)});
fachSimpleCursorAdapter.swapCursor(myDb.zeigeFaecher()); // Tell the adapter about the new cursor
return true;
}
});
}
}
HINWEIS als _id
Spalte ist immer eindeutig. Diese Methode löscht nur die spezifische Zeile, nicht mehrere Zeilen, wenn die angezeigten Werte nicht eindeutig sind.