Android ListView长按待办项无反应,如何同步删除列表及SQLite数据
解决方法
你当前的问题有两个核心点:
- 长按逻辑里只删除了内存中列表的数据,没有调用数据库删除方法
- 现有列表只存了待办文本内容,没有关联数据库对应的行
_id,无法直接调用你的deleteItem方法
按以下步骤修改即可:
步骤1:将DatabaseHelper改为MainActivity的全局成员变量
方便在长按回调中调用数据库方法,修改MainActivity的成员变量声明:
public class MainActivity extends AppCompatActivity { // 新增全局helper变量 private DatabaseHelper helper; private ArrayList<String> items; private ArrayAdapter<String> itemsAdapter; private ListView lvItems; private EditText e;
同时修改onCreate里的helper初始化代码,删掉前面的final修饰:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 去掉final,给全局helper赋值 helper = new DatabaseHelper(this); // 其余原有代码不变...
步骤2:新建实体类关联待办内容和数据库ID
因为需要同时存待办文本和对应的数据库_id,新建一个TodoItem.java类:
public class TodoItem { private long id; private String content; public TodoItem(long id, String content) { this.id = id; this.content = content; } public long getId() { return id; } public String getContent() { return content; } // 重写toString,保证适配器展示内容和之前完全一致 @Override public String toString() { return content; } }
步骤3:修改数据库查询方法返回带ID的实体列表
修改DatabaseHelper中的getAllAcontacts方法,改为返回ArrayList<TodoItem>,查询时同时取_id和待办内容:
注意替换代码中的
你的待办内容列名为你数据库中存储待办文本的字段名
public ArrayList<TodoItem> getAllAcontacts() { ArrayList<TodoItem> todoList = new ArrayList<>(); SQLiteDatabase db = this.getReadableDatabase(); // 查询的时候同时取_id和内容字段 Cursor cursor = db.rawQuery("SELECT _id, 你的待办内容列名 FROM " + LIST_TABLE_NAME, null); if (cursor.moveToFirst()) { do { long id = cursor.getLong(cursor.getColumnIndexOrThrow("_id")); String content = cursor.getString(cursor.getColumnIndexOrThrow("你的待办内容列名")); todoList.add(new TodoItem(id, content)); } while (cursor.moveToNext()); } cursor.close(); db.close(); return todoList; }
步骤4:同步修改MainActivity的列表类型
调整MainActivity中的列表和适配器声明:
// 把原来的String泛型改成TodoItem private ArrayList<TodoItem> items; private ArrayAdapter<TodoItem> itemsAdapter;
其余初始化适配器的代码不需要修改,因为我们重写了TodoItem的toString方法,展示效果和之前完全一致。
步骤5:修改长按回调逻辑,同步删除数据库和列表数据
修改setOnItemLongClickListener里的代码:
@Override public boolean onItemLongClick(AdapterView<?> adapter, View item, int pos, long id) { // 1. 拿到当前点击项对应的数据库ID long targetItemId = items.get(pos).getId(); // 2. 先删除数据库中的对应数据 helper.deleteItem(targetItemId); // 3. 再删除内存列表中的对应项,刷新界面 items.remove(pos); itemsAdapter.notifyDataSetChanged(); Toast.makeText(MainActivity.this, "删除成功", Toast.LENGTH_SHORT).show(); return true; }
长按无反应的额外排查
如果修改后长按还是没有触发回调,可以在你的ListView的item布局根节点添加下面的属性,避免子控件抢焦点:
android:descendantFocusability="blocksDescendants" android:longClickable="true"
内容的提问来源于stack exchange,提问作者Mahin Rahman
相关产品推荐
相关产品推荐

