Kort sagt skal du være i stand til at skelne en række til sletning ved de data, der er tilgængelige for ListView. Hvis værdien hentes fra markøren, som 2. kolonne (dvs. strengen udtrukket ved hjælp af res.getString(1))
, og værdien bliver unik , kan du hente dette og bruge det til sletningen.
Der er dog et par problemer ved at bruge en ListAdapter
vil sandsynligvis ikke være tilstrækkeligt. Der er andre adaptere, såsom en ArrayAdapter, der tilbyder flere funktioner og vigtigere en notifyDatasetChanged
metode (der vil opdatere den tilknyttede ListView).
Det er spild at oprette en ny adapter for hver iteration af markøren. Så adapteren skal oprettes uden for løkken og kun én gang.
Jeg vil foreslå, at sletning ved elementklik vil være for tilbøjelig til utilsigtet klik, sletning af element LongClick ville være langt mindre tilbøjelig til utilsigtet sletning.
Hvis du flytter variable til klassevariable, behøver du ikke at erklære dem som endelige.
Så baseret på ovenstående kunne du have :-
Array Adapter-metode
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));
}
}
}
Sammen med ovenstående er deletRow
metoden er :-
public int deleteRow(String col2) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
- hvor
- TB001 er en konstant streng, der er sat til tabellens navn.
- COL_TB001_DATA er kolonnenavnet på 2. kolonne.
ADVARSEL Løsningen ovenfor vil kun fungere korrekt, hvis 2. kolonne indeholder unikke data, ellers ville flere rækker blive slettet.
Der er også den antagelse, at sletningen virker, det kunne være bedre at have :-
@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
}
Markøradaptermetode
Der er dog andre adaptere, der er egnede til markører, som kunne gøre op med behovet for et mellemliggende array. Du kan bruge en CursorAdapter
. For en CursorAdapter
et kolonnenavn _id
er påkrævet, og denne kolonne skal være lang og identificere rækken på en uklar måde. Hensigten og dermed navnet er, at et alias for rovid bruges (derfor også hvorfor CONSTANT BaseColumns._ID
findes).
Et alias for rovid oprettes ved at definere ?? INTEGER PRIMARY KEY
hvor ?? er kolonnenavnet. Så ideelt set bør tabellen defineres inklusive en kolonnedefinition med _id INTEGER PRIMARY KEY
for eksempel. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT)
(du kan følge INTEGER PRIMARY KEY
med søgeordet AUTOINCREMENT, men generelt ville du ikke gøre det, da det har overheads SQLite Autoincrement)
Hvis din tabel ikke har en sådan kolonne, kan du altid oprette en kolonne i markøren, når du forespørger dataene, ved at bruge rowid AS _id
for eksempel. hvis din SQL svarer til SELECT * FROM mytable
så kan du bruge SELECT *, rowid AS _id FROM mytable
.
I dette eksempel aktien SimpleCursorAdapter
vil blive brugt, kan koden være:-
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;
}
});
}
}
BEMÆRK som _id
kolonne vil altid være unik. Denne metode vil kun slette den specifikke række, ikke flere rækker, hvis de viste værdier ikke er unikke.