仅Android端出现CursorIndexOutOfBoundsException问题求助
问题分析与解决方案
这个问题的核心原因是SQLite Cursor的初始位置特性,以及libGDX的gdx-sqlite在桌面和Android平台上的Cursor实现差异。
为什么会触发异常?
当你通过rawQuery获取到Cursor对象时,它的初始位置是**-1**(也就是指向第一条数据的前方),此时直接调用getLong(0)这类获取数据的方法,必然会触发CursorIndexOutOfBoundsException——因为当前位置根本没有有效数据。
你桌面端能正常运行,大概率是因为gdx-sqlite的桌面平台实现(比如基于SQLiteJDBC)在返回Cursor时,默认帮你移动到了第一条数据的位置;但Android平台的Cursor严格遵循原生Android SQLite的规范,初始位置保持在-1,必须手动移动到有效行才能读取数据。
你的两段代码差异对比
- 报错的代码:直接在获取Cursor后调用
getLong(0),没有移动Cursor到有效行try { cursorSettings = dbHandler.rawQuery("SELECT "+COLUMN_SETTING+" FROM "+TABLE_SETTINGS+" WHERE "+COLUMN_SETTINGSID+" =13"); System.out.println(cursorSettings.getLong(0)); // 初始位置为-1,直接读取触发异常 } catch (SQLiteGdxException e) { e.printStackTrace(); } - 正常运行的代码:通过
while (cursorSettings.next())循环,第一次调用next()就会将Cursor从-1移动到0(第一条数据的位置),后续每次循环移动到下一行,所以能正常读取try { cursorSettings = dbHandler.rawQuery("SELECT * FROM "+TABLE_SETTINGS); } catch (SQLiteGdxException e) { e.printStackTrace(); } while (cursorSettings.next()) { Gdx.app.log("FromDb", String.valueOf(cursorSettings.getString(1))); }
修复方案
在读取Cursor数据之前,必须先调用moveToFirst()或者next()来移动到有效行,同时还要判断是否存在数据(避免查询结果为空的情况):
方案1:使用moveToFirst()(适合明确最多一条结果的场景)
try { cursorSettings = dbHandler.rawQuery("SELECT "+COLUMN_SETTING+" FROM "+TABLE_SETTINGS+" WHERE "+COLUMN_SETTINGSID+" =13"); // 先移动到第一条数据,同时判断是否存在匹配结果 if (cursorSettings.moveToFirst()) { System.out.println(cursorSettings.getLong(0)); } else { // 处理没有找到对应数据的情况 Gdx.app.log("DBInfo", "No settings found with ID 13"); } } catch (SQLiteGdxException e) { e.printStackTrace(); } finally { // 用完Cursor记得关闭,避免数据库资源泄漏 if (cursorSettings != null) { cursorSettings.close(); } }
方案2:使用next()(适合不确定结果行数的场景)
try { cursorSettings = dbHandler.rawQuery("SELECT "+COLUMN_SETTING+" FROM "+TABLE_SETTINGS+" WHERE "+COLUMN_SETTINGSID+" =13"); while (cursorSettings.next()) { System.out.println(cursorSettings.getLong(0)); // 因为你的查询是按ID筛选,理论上最多一条数据,循环一次就会退出 } } catch (SQLiteGdxException e) { e.printStackTrace(); } finally { if (cursorSettings != null) { cursorSettings.close(); } }
额外提醒
不管是哪个平台,都应该养成用完Cursor就关闭的习惯,避免数据库资源泄漏;同时一定要处理查询结果为空的情况,防止出现意外异常。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

