简而言之,您需要能够通过 ListView 可用的数据来区分要删除的行。如果从光标检索到的值,作为第二列(即使用提取的字符串res.getString(1))
, 并且价值将是独一无二的,您可以检索它并将其用于删除。
然而,使用ListAdapter
可能还不够。还有其他适配器,例如 ArrayAdapter,它提供更多功能,重要的是notifyDatasetChanged
方法(将刷新关联的 ListView)。
为游标的每次迭代创建一个新的适配器是一种浪费。因此适配器应该在循环之外创建,并且只创建一次。
我建议在项目单击上删除太容易发生意外点击,而在项目 LongClick 上删除则不太容易发生意外删除。
如果将变量移动为类变量,则不必将它们声明为最终变量。
因此,根据上述内容,您可以:-
阵列适配器方法
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));
}
}
}
除了上述内容之外deletRow
方法是:-
public int deleteRow(String col2) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TB001,COL_TB001_DATA + "=?",new String[]{col2});
}
- where
-
TB001是设置为表名称的常量字符串。
-
COL_TB001_数据是第二列的列名称。
WARNING仅当第二列包含唯一数据时,上述解决方案才能正常工作,否则将删除多行。
还有一种假设是删除有效,最好是:-
@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
}
游标适配器方法
然而,还有其他适合游标的适配器可以消除对中间数组的需要。你可以利用CursorAdapter
. For a CursorAdapter
列名_id
是必需的,该列应该是long并且还唯一标识该行。其意图和名称是rowid使用(因此也是为什么 CONSTANTBaseColumns._ID
存在)。
的别名rowid是通过定义创建的?? INTEGER PRIMARY KEY
在哪里 ??是列名称。因此,理想情况下,表的定义应包括列定义_id INTEGER PRIMARY KEY
e.g. CREATE mytable (_id INTEGER PRIMARY KEY, myothercolumn TEXT)
(您可以关注INTEGER PRIMARY KEY
使用关键字 AUTOINCRMENT,但通常您不会这样做,因为它有开销SQLite自动增量 https://sqlite.org/autoinc.html)
如果您的表没有这样的列,那么您可以在查询数据时始终在游标中创建一列,方法是使用rowid AS _id
例如如果你的 SQL 等于SELECT * FROM mytable
那么你可以使用SELECT *, rowid AS _id FROM mytable
.
在这个例子中,股票SimpleCursorAdapter
将被使用,代码可以是:-
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;
}
});
}
}
NOTE as the _id
列将始终是唯一的,如果显示的值不唯一,此方法将仅删除特定行而不是多行。