Android SQLite Cursor初始索引-1越界报错问题求助
问题排查结果
直接崩溃原因
- 游标未移动即读取数据:Android SQLite返回的
Cursor初始位置固定为-1,指向第一条查询结果的前置位置,必须主动调用移动方法将游标指向有效行才能读取数据。原有遍历逻辑仅做次数循环,全程未移动游标,游标始终停在-1位置,直接触发CursorIndexOutOfBoundsException。 - 列索引查询参数错误:
dbOpener类中定义的数据库实际列名为ITEM/URGENT/_id,但MainActivity中调用getColumnIndex()时传入的是Java常量名字符串"COL_ITEM_NAME"/"COL_URGENT"/"COL_ID",数据库中不存在对应列名,返回的列索引全为-1,即便游标位置正确也无法读取数据。
其他连带逻辑缺陷
- 数据加载时机错误:数据库读取操作在ListView绑定空adapter之后执行,读取完成后未调用刷新方法,历史存储的数据不会显示到列表中。
- 游标未关闭:读取完数据未主动关闭Cursor,会造成内存泄漏。
- 删除逻辑不同步:长按删除仅移除了内存集合中的条目,未同步删除数据库中对应记录,应用重启后被删除的内容会重新出现。
dbOpener中预定义的columns数组重复写入COL_ITEM_NAME、遗漏_id字段,后续如果用该数组做查询参数会触发列不存在错误。- 紧急状态Switch监听逻辑错误:原有点击监听强制把开关设为选中状态,用户无法切回非紧急状态,交互失效。
修复代码
1. 替换数据库读取遍历逻辑
将MainActivity中原有读取Cursor的代码替换为如下内容:
cursor = dbOpener.readData(); // 直接引用dbOpener中定义的列名常量,避免硬编码字符串写错 int nameColIndex = cursor.getColumnIndex(dbOpener.COL_ITEM_NAME); int urgentColIndex = cursor.getColumnIndex(dbOpener.COL_URGENT); int idColIndex = cursor.getColumnIndex(dbOpener.COL_ID); // 先移动到首行判断是否有数据,循环中主动移动游标到下一行 if (cursor.moveToFirst()) { do { String name = cursor.getString(nameColIndex); int urgentHolder = cursor.getInt(urgentColIndex); boolean isUrgent = urgentHolder == 1; arrayList.add(new toDoItem(name, isUrgent)); } while (cursor.moveToNext()); } // 用完关闭游标 cursor.close(); // 加载完数据刷新列表 adapter.notifyDataSetChanged();
2. 修正dbOpener中的列数组
将原有错误的columns定义替换为:
String [] columns = {dbOpener.COL_ID, dbOpener.COL_ITEM_NAME, dbOpener.COL_URGENT};
3. 修正Switch交互逻辑
删除原有的urgent.setOnClickListener代码,替换为选中状态监听:
urgent.setOnCheckedChangeListener((buttonView, isChecked) -> urgent.setChecked(isChecked));
4. 补充删除的数据库同步逻辑
在长按删除的正按钮回调中,增加数据库删除操作,保证内存和数据库数据一致。
内容的提问来源于stack exchange,提问作者ReginaldRey
相关产品推荐
相关产品推荐

