You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:42:25