Krótko mówiąc, musisz być w stanie odróżnić wiersz do usunięcia na podstawie danych dostępnych dla ListView. Jeśli wartość pobrana z kursora, jako druga kolumna (tj. String wyodrębniony przy użyciu res.getString(1))
, a wartość będzie unikalna , możesz go pobrać i użyć do usunięcia.
Istnieje jednak kilka problemów związanych z używaniem ListAdapter
prawdopodobnie nie wystarczy. Istnieją inne adaptery, takie jak ArrayAdapter, które oferują więcej funkcji i, co ważne, notifyDatasetChanged
metoda (która odświeży powiązany widok ListView).
Marnotrawstwem jest tworzenie nowego adaptera dla każdej iteracji kursora. Dlatego adapter powinien być utworzony poza pętlą i tylko raz.
Sugeruję, że usunięcie kliknięcia elementu będzie zbyt podatne na przypadkowe kliknięcie, a usunięcie elementu LongClick będzie znacznie mniej podatne na przypadkowe usunięcie.
Jeśli przenosisz zmienne jako zmienne klasowe, nie musisz deklarować ich jako ostatecznych.
Więc w oparciu o powyższe, możesz mieć:-
Metoda adaptera tablicy
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));
}
}
}
Wraz z powyższym deletRow
metoda to :-
public int deleteRow(String col2) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
- gdzie
- TB001 jest stałym ciągiem, który jest ustawiony na nazwę tabeli.
- COL_TB001_DATA to nazwa kolumny drugiej kolumny.
OSTRZEŻENIE Powyższe rozwiązanie będzie działać poprawnie tylko wtedy, gdy druga kolumna zawiera unikalne dane, w przeciwnym razie wiele wierszy zostanie usuniętych.
Istnieje również założenie, że usuwanie działa, lepiej byłoby mieć :-
@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
}
Metoda adaptera kursora
Istnieją jednak inne adaptery odpowiednie dla Cursors, które mogą wyeliminować potrzebę pośredniej tablicy. Możesz użyć CursorAdapter
. Dla Adaptera kursora
nazwa kolumny _id
jest wymagana, a ta kolumna powinna być długa a także jednoznacznie identyfikować wiersz. Intencją i stąd nazwa jest to, że alias rowidu jest używany (stąd też dlaczego STAŁY BaseColumns._ID
istnieje).
Alias rowidu jest tworzony przez zdefiniowanie _id INTEGER PRIMARY KEY
np. CREATE mojatabela (_id INTEGER PRIMARY KEY, mojainnakolumna TEXT)
(możesz śledzić INTEGER PRIMARY KEY
ze słowem kluczowym AUTOINCREMENT, jednak generalnie nie zrobiłbyś tego, ponieważ ma on narzuty na autoinkrementację SQLite)
Jeśli Twoja tabela nie ma takiej kolumny, zawsze możesz utworzyć kolumnę w kursorze podczas zapytania o dane, używając rowid AS _id
np. jeśli SQL równa się SELECT * FROM mytable
wtedy możesz użyć SELECT *, rowid AS _id FROM mytable
.
W tym przykładzie giełdowy SimpleCursorAdapter
zostanie użyty, kod może wyglądać tak:-
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;
}
});
}
}
UWAGA jako _id
kolumna będzie zawsze unikalna, ta metoda usunie tylko określony wiersz, a nie wiele wierszy, jeśli wyświetlane wartości nie są unikatowe.