ListView 顯示資料庫資料,長按或點擊項目彈出確認對話框,確認後刪除該筆資料並更新列表。
public class DatabaseHandler extends SQLiteOpenHelper {
// ... 現有代碼 ...
// 依 ID 刪除單筆資料
public boolean deleteLabel(long id) {
SQLiteDatabase db = this.getWritableDatabase();
int rows = db.delete(TABLE_LABELS, KEY_ID + " = ?", new String[]{String.valueOf(id)});
db.close();
return rows > 0;
}
// 刪除所有資料 (慎用)
public void deleteAllLabels() {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_LABELS, null, null);
db.close();
}
}
ListView listView = findViewById(R.id.list_view);
DatabaseHandler db = new DatabaseHandler(this);
List labels = db.getAllLabels();
ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, labels);
listView.setAdapter(adapter);
// 長按刪除 (推薦,避免誤觸)
listView.setOnItemLongClickListener((parent, view, position, id) -> {
showDeleteConfirmDialog(position, id); // id 即為資料庫 _id (若 Adapter 正確設定)
return true; // 消費長按事件
});
// 或點擊刪除
listView.setOnItemClickListener((parent, view, position, id) -> {
showDeleteConfirmDialog(position, id);
});
private void showDeleteConfirmDialog(final int position, final long id) {
new AlertDialog.Builder(this)
.setTitle("確認刪除")
.setMessage("確定要刪除此項目嗎?")
.setPositiveButton("刪除", (dialog, which) -> {
// 執行刪除
DatabaseHandler db = new DatabaseHandler(this);
if (db.deleteLabel(id)) {
// 刪除成功:更新 Adapter 資料源
labels.remove(position); // 從列表移除
adapter.notifyDataSetChanged(); // 通知 ListView 更新
Toast.makeText(this, "已刪除", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "刪除失敗", Toast.LENGTH_SHORT).show();
}
db.close();
})
.setNegativeButton("取消", null)
.show();
}
問題:OnItemClickListener 的 id 參數**不一定**等於資料庫 _id,取決於 Adapter 實作。
Cursor cursor = db.getAllLabelsCursor(); // 回傳包含 _id 的 Cursor
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
this, R.layout.item, cursor,
new String[]{"name"}, new int[]{R.id.text}, 0);
listView.setAdapter(adapter);
// 此時 onItemClick 的 id 參數即為資料庫 _id
listView.setOnItemClickListener((parent, view, position, id) -> {
// id 就是 _id,可直接 db.deleteLabel(id)
});
// 維護一個平行 List 儲存對應的 _id
List labelNames = new ArrayList<>();
List labelIds = new ArrayList<>();
Cursor cursor = db.getAllLabelsCursor();
while (cursor.moveToNext()) {
labelNames.add(cursor.getString(cursor.getColumnIndex("name")));
labelIds.add(cursor.getLong(cursor.getColumnIndex("_id")));
}
ArrayAdapter adapter = new ArrayAdapter<>(this, ..., labelNames);
listView.setAdapter(adapter);
listView.setOnItemClickListener((parent, view, position, id) -> {
long dbId = labelIds.get(position); // 取得對應 _id
deleteItem(dbId, position);
});
// ArrayAdapter 情況
labels.remove(position);
labelIds.remove(position); // 同步移除 ID
adapter.notifyDataSetChanged();
// CursorAdapter 情況 (需重新查詢或使用 CursorLoader)
cursor.requery(); // API 11+ 棄用,建議用 LoaderManager/CursorLoader
// 或
new LoaderManager.LoaderCallbacks() {
// 實作 onCreateLoader, onLoadFinished, onLoaderReset
// 刪除後呼叫 getLoaderManager().restartLoader(LOADER_ID, null, this);
}.initLoader(LOADER_ID, null, this);
// DAO
@Dao interface LabelDao {
@Query("SELECT * FROM labels ORDER BY name") LiveData> getAll();
@Delete void delete(Label label);
}
// Repository -> ViewModel -> LiveData 觀察
// Adapter 提交 List 更新 (ListAdapter + DiffUtil)
// 點擊刪除:viewModel.delete(label) -> 資料庫更新 -> LiveData 通知 -> UI 自動更新