В идеале вы должны использовать первичный ключ, который можно найти в ваших представлениях (или, наоборот, использовать в качестве первичного ключа значение, которое уже используется где-то для извлечения). Поскольку ваш первичный ключ здесь является полем auto_increment
, нет реальной надежной корреляции между ним и представлением, которое вы пытаетесь удалить (по крайней мере из того, что я вижу в вашем коде). Один из подходов состоит в том, чтобы использовать пользовательский Adapter
для своего списка, а не ArrayAdapter
, и использовать методы View.setTag()
и View.getTag()
для хранения первичного ключа в каждом из элементов вашего Списка. Вы можете увидеть, как это сделать здесь , а также несколько интерактивных обучающих программ по адаптеру.
Если ваш макет activity_listitem
имеет TextView
с идентификатором text_view
, где вы отображаете текст, извлеченный из вашей базы данных, и к которому вы добавили тег, хранящий первичный ключ, вы можете сделатьв вашей основной деятельности:
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
TextView textView = (TextView) view.findViewById(R.id.text_view);
final Integer which_item = (Integer) textView.getTag(); //Assuming you stored the ID as an Integer
int rowsDeleted = bookmarksDB.deleteSpecificContent(which_item);
if(rowsDeleted == 0){ //should be 1, since we're deleting by Primary Key
//if you would like like, handle if nothing was deleted
}
return true;
}
});
А в вашем классе BookmarksDatabase:
public int deleteSpecificContents(int id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TABLE_NAME, COL1 + "=?", new String[]{Integer.toString(id)});
}
Другой подход, если вы не хотите использовать пользовательский Adapter
, будетопределить элемент, который вы хотите удалить, используя его позицию в списке. Вы можете сделать это, выполнив запрос к базе данных и итерируя Cursor
, пока он не совпадет с позицией вашего элемента в списке.
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Cursor data = bookmarkDB.getListContents();
int i = 0;
while(data.moveToNext()){
if(i == position){
break;
}
i++;
}
int rowsDeleted = bookmarkDB.deleteSpecificContent(data.getInt(0));
//again, handle if rowsDeleted != 1 if you want
return true;
}
});
Ваш метод BookmarkDatabase.deleteSpecificContent()
точно такой же, как в первомподход к этому - единственная разница в том, как вы определяете идентификатор элемента, который будет удален. Если вы не хотите обрабатывать случай, когда deleteSpecificContent()
не возвращает 1 (если я не пропускаю здесь что-то важное, то должно всегда возвращать 1 в вашем случае использования), смело изменяйте его подписьдо void
, а не int
.
Обратите внимание, что этот второй подход более дорогой, чем первый, поскольку он требует дополнительного запроса к базе данных и может многократно повторять Cursor
. Хотя для этого требуется гораздо меньше нового / измененного кода, его использование может быть нецелесообразным (я, честно говоря, не могу сказать наверняка. Это , вероятно, хорошо для вашего случая использования, в зависимости от размера вашей базы данных, но- полное раскрытие - я не достаточно опытен с Android, чтобы сделать этот вызов. Используйте по своему усмотрению).