Singkatnya, Anda harus dapat membedakan baris untuk dihapus dengan data yang tersedia untuk ListView. Jika nilai diambil dari kursor, sebagai kolom ke-2 (yaitu String diekstraksi dengan menggunakan res.getString(1))
, dan nilainya akan menjadi unik , Anda dapat mengambil ini dan menggunakannya untuk penghapusan.
Namun, ada beberapa masalah, menggunakan ListAdapter
mungkin tidak akan cukup. Ada adaptor lain, seperti ArrayAdapter yang menawarkan lebih banyak fitur dan yang terpenting notifyDatasetChanged
metode (yang akan menyegarkan ListView terkait).
Adalah sia-sia untuk membuat adaptor baru untuk setiap iterasi kursor. Jadi adaptor harus dibuat di luar loop dan sekali saja.
Saya menyarankan bahwa menghapus pada klik item akan terlalu rentan terhadap klik yang tidak disengaja, menghapus item LongClick akan jauh lebih rentan terhadap penghapusan yang tidak disengaja.
Jika Anda memindahkan variabel menjadi variabel kelas, Anda tidak perlu mendeklarasikannya sebagai final.
Jadi berdasarkan hal di atas, Anda dapat memiliki :-
Metode Adaptor Array
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));
}
}
}
Bersamaan dengan deletRow
di atas caranya :-
public int deleteRow(String col2) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
- dimana
- TB001 adalah String konstan yang disetel ke nama tabel.
- COL_TB001_DATA adalah nama kolom dari kolom ke-2.
PERINGATAN Solusi di atas hanya akan berfungsi dengan benar jika kolom ke-2 berisi data unik, jika tidak, beberapa baris akan dihapus.
Ada juga anggapan bahwa penghapusan berhasil, mungkin lebih baik memiliki :-
@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
}
Metode Adaptor Kursor
Namun, ada adaptor lain yang cocok untuk Kursor yang dapat menghilangkan kebutuhan akan Array perantara. Anda dapat menggunakan CursorAdapter
. Untuk CursorAdapter
nama kolom _id
wajib diisi dan kolom ini harus panjang dan juga mengidentifikasi baris dengan tidak jelas. Maksud dan namanya adalah alias dari rowid digunakan (karenanya juga mengapa CONSTANT BaseColumns._ID
ada).
Alias dari rowid dibuat dengan mendefinisikan ?? INTEGER PRIMARY KEY
di mana ?? adalah nama kolom. Jadi idealnya tabel harus didefinisikan termasuk definisi kolom dengan _id INTEGER PRIMARY KEY
misalnya CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT)
(Anda dapat mengikuti INTEGER PRIMARY KEY
dengan kata kunci AUTOINCREMENT, namun umumnya Anda tidak akan melakukannya, karena memiliki overhead SQLite Autoincrement)
Jika tabel Anda tidak memiliki kolom seperti itu, Anda selalu dapat membuat kolom di kursor saat mengkueri data, dengan menggunakan rowid AS _id
misalnya jika Anda SQL sama dengan SELECT * FROM mytable
maka Anda dapat menggunakan SELECT *, rowid AS _id FROM mytable
.
Dalam contoh ini stok SimpleCursorAdapter
akan digunakan, kodenya bisa :-
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;
}
});
}
}
CATATAN sebagai _id
kolom akan selalu unik metode ini hanya akan menghapus baris tertentu bukan beberapa baris jika nilai yang ditampilkan tidak unik.