Tóm lại, bạn cần có khả năng phân biệt một hàng để xóa bằng dữ liệu có sẵn cho ListView. Nếu giá trị được truy xuất từ con trỏ, dưới dạng cột thứ 2 (tức là Chuỗi được trích xuất bằng cách sử dụng res.getString(1))
, và giá trị sẽ là duy nhất , bạn có thể lấy nó và sử dụng nó để xóa.
Tuy nhiên, có một số vấn đề khi sử dụng ListAdapter
có lẽ sẽ không đủ. Có những bộ điều hợp khác, chẳng hạn như ArrayAdapter cung cấp nhiều tính năng hơn và quan trọng là notifyDatasetChanged
(sẽ làm mới ListView được liên kết).
Thật lãng phí khi tạo một bộ điều hợp mới cho mỗi lần lặp lại con trỏ. Vì vậy, bộ điều hợp nên được tạo bên ngoài vòng lặp và chỉ một lần.
Tôi đề nghị rằng xóa khi nhấp vào mục sẽ quá dễ bị nhấp vào tình cờ, xóa trên LongClick mục sẽ ít bị xóa do tình cờ hơn nhiều.
Nếu bạn di chuyển các biến thành biến lớp, bạn không cần phải khai báo chúng là biến cuối cùng.
Vì vậy, dựa trên những điều trên, bạn có thể có:-
Phương thức Bộ điều hợp mảng
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));
}
}
}
Cùng với deletRow
ở trên phương pháp là:-
public int deleteRow(String col2) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
- ở đâu
- TB001 là một chuỗi không đổi thatis được đặt thành tên của bảng.
- COL_TB001_DATA là tên cột của cột thứ 2.
CẢNH BÁO Giải pháp trên sẽ chỉ hoạt động chính xác nếu cột thứ 2 chứa dữ liệu duy nhất, nếu không nhiều hàng sẽ bị xóa.
Cũng có giả định rằng việc xóa hoạt động, tốt hơn nên có:-
@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
}
Phương thức Bộ điều hợp con trỏ
Tuy nhiên, có những bộ điều hợp khác phù hợp với Con trỏ có thể loại bỏ nhu cầu về Mảng trung gian. Bạn có thể sử dụng CursorAdapter
. Đối với CursorAdapter
tên cột _id
là bắt buộc và cột này phải là dài và cũng xác định hàng một cách khó hiểu. Ý định và do đó tên là một bí danh của người hàng xóm được sử dụng (do đó cũng là lý do CONSTANT BaseColumns._ID
tồn tại).
Bí danh của rowid được tạo bằng cách xác định ?? INTEGER PRIMARY KEY
ở đâu ?? là tên cột. Vì vậy, lý tưởng nhất là bảng nên được xác định bao gồm định nghĩa cột với _id INTEGER PRIMARY KEY
ví dụ. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT)
(bạn có thể theo dõi INTEGER PRIMARY KEY
với từ khóa AUTOINCREMENT, tuy nhiên thông thường bạn sẽ không làm như vậy, vì nó có chi phí tự động tăng SQLite)
Nếu bảng của bạn không có cột như vậy thì bạn luôn có thể tạo một cột trong con trỏ khi truy vấn dữ liệu, bằng cách sử dụng rowid AS _id
ví dụ. nếu bạn SQL tương đương với SELECT * FROM mytable
thì bạn có thể sử dụng SELECT *, rowid AS _id FROM mytable
.
Trong ví dụ này, kho SimpleCursorAdapter
sẽ được sử dụng, mã có thể là:-
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;
}
});
}
}
LƯU Ý dưới dạng _id
cột sẽ luôn là duy nhất phương pháp này sẽ chỉ xóa hàng cụ thể chứ không phải nhiều hàng nếu các giá trị được hiển thị không phải là duy nhất.