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

如何调试Android API30+下的CursorIndexOutOfBoundsException错误

Android 11+版本出现CursorIndexOutOfBoundsException问题排查与解决

我是一名开发新手,正在为学校项目制作一款健康应用。该应用在Android 11(API 30)上运行正常,但在Android 11以上(API 30+)版本中出现错误。

报错代码

private fun refreshMe(){
    val helper = profileHelper(applicationContext)
    val db = helper.readableDatabase
    val rs = db.rawQuery("SELECT * FROM uProfile", null)

    rs.moveToLast()
    nama.text = rs.getString(1) //THE ERROR HAPPEN HERE
    umur.text = rs.getString(2)
    jk.text = rs.getString(3)
    data.text = rs.getString(4)
    kadarAu.text = rs.getString(5)
    kadarGd.text = rs.getString(6)
    kadarHb.text = rs.getString(7)
    kadarCh.text = rs.getString(8)
    kadarTdSis.text = rs.getString(9)
    kadarTdDia.text = rs.getString(10)
    rs.close()
}

错误日志

FATAL EXCEPTION: main

Process: com.lhsproj.labhealthpocket, PID: 10098
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.lhsproj.labhealthpocket/com.lhsproj.labhealthpocket.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8177)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0
    at android.database.AbstractCursor.checkPosition(AbstractCursor.java:521)
    at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:139)
    at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:53)
    at com.lhsproj.labhealthpocket.MainActivity.refreshMe(MainActivity.kt:63)
    at com.lhsproj.labhealthpocket.MainActivity.onCreate(MainActivity.kt:251)
    at android.app.Activity.performCreate(Activity.java:8595)
    at android.app.Activity.performCreate(Activity.java:8573)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3764)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:205) 
    at android.os.Looper.loop(Looper.java:294) 
    at android.app.ActivityThread.main(ActivityThread.java:8177) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) 

问题核心

错误提示CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0说明:查询返回的游标是空的(表uProfile中没有数据),但你直接调用rs.moveToLast()后未做判断就读取数据,此时游标仍处于初始位置-1,触发崩溃。

Android 11+出现问题的大概率原因是存储权限变更,导致数据库文件未正确创建或读取,表中无数据。

修复方案

  1. 先处理空游标,避免崩溃
    修改refreshMe()方法,先判断游标是否有有效数据:

    private fun refreshMe(){
        val helper = profileHelper(applicationContext)
        val db = helper.readableDatabase
        val rs = db.rawQuery("SELECT * FROM uProfile", null)
    
        // 先判断是否能移动到最后一条数据
        if (rs.moveToLast()) {
            nama.text = rs.getString(1)
            umur.text = rs.getString(2)
            jk.text = rs.getString(3)
            data.text = rs.getString(4)
            kadarAu.text = rs.getString(5)
            kadarGd.text = rs.getString(6)
            kadarHb.text = rs.getString(7)
            kadarCh.text = rs.getString(8)
            kadarTdSis.text = rs.getString(9)
            kadarTdDia.text = rs.getString(10)
        } else {
            // 无数据时的默认显示逻辑
            nama.text = "请完善个人资料"
            umur.text = "--"
            jk.text = "--"
            // 其余控件也设置默认值
        }
        rs.close()
    }
    
  2. 排查数据库权限与创建逻辑

    • 检查自定义profileHelper(SQLiteOpenHelper子类)的数据库存储路径,Android 11+建议使用内部存储路径(如getDatabasePath()),避免使用外部存储的旧路径;
    • 确认profileHelper的onCreate()方法是否正确创建了uProfile表,字段数量要匹配你读取的索引(索引1到10对应至少11个字段,索引0通常是主键);
    • 卸载旧版本后重新安装,避免旧数据库缓存导致的异常。
  3. 代码优化建议

    • 不要直接用索引读取字段,改用getColumnIndex(),避免表结构变更引发错误:
      nama.text = rs.getString(rs.getColumnIndex("nama_column_name"))
      
    • 用try-finally确保游标和数据库资源正确释放:
      private fun refreshMe(){
          val helper = profileHelper(applicationContext)
          val db = helper.readableDatabase
          var rs: Cursor? = null
          try {
              rs = db.rawQuery("SELECT * FROM uProfile", null)
              if (rs.moveToLast()) {
                  // 赋值逻辑
              }
          } finally {
              rs?.close()
              db.close()
          }
      }
      

内容的提问来源于stack exchange,提问作者Lalu Habib Sasiwimba

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 15:17:33