如何调试 CursorIndexOutOfBoundsException 错误

How to debug a CursorIndexOutOfBoundsException error

提问人:Lalu Habib Sasiwimba 提问时间:10/29/2023 最后编辑:halferLalu Habib Sasiwimba 更新时间:10/30/2023 访问量:40

问:

我是一名初学者,试图为我的学校项目构建一个健康应用程序

当我使用 Android 11 (API 30) 时,该程序运行良好。当我使用高于 11 (API 30+) 的 Android 时发生错误。

发生错误的代码:

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) 

我之前尝试过 Stack Overflow 的几种解决方案,但我发现它们很难在我的项目中实现。

android 数据库 sqlite kotlin android-studio

评论


答:

0赞 MikeT 10/30/2023 #1

您应该始终检查移动(在您的情况下)是否成功。所有方法都返回一个布尔值,如果移动成功,则返回 true,如果无法进行移动,则返回 false。moveToLastmove????

  • -1 表示在第一行之前的位置,因此 DID DID NOT MAKE THE MOVEmoveToLastRow

此外

通常不建议对游标索引值进行硬编码。相反,建议通常使用 Cursor 的 or 方法来确定列的索引及其有效性(如果列名无效,则为 -1,如果引发,则为 IllegalArgumentException)。getColumnIndexgetColumnIndexOrThrow

参见游标

所以你可以有类似的东西:-

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

    val namaCI = rs.getColumnIndex("nama")
    val umrCI = rs.getColumnIndex("umur")
    val jkCI = rs.getColumnIndex("jk")
    val dataCI = rs.getColumnIndex("data")
    val kadarAuCI = rs.getColumnIndex("kadarAu")
    val kadarGdCI = rs.getColumnIndex("kadarGd")
    val kadarHbCI = rs.getColumnIndex("kadarHb")
    val kadarChCI = rs.getColumnIndex("kadaraCh")
    val kadarTdSisCI = rs.getColumnIndex("kadarTdSis")
    val kadarTdDiaCI = rs.getColumnIndex("kadarTdDia")
    val ok = namaCI >=0 && umrCI >= 0 && jkCI >= 0 && dataCI >0 && kadarAuCI >= 0 && kadarGdCI >= 0 && kadarHbCI >= 0 && kadarChCI >= 0 && kadarTdSisCI >= 0 && kadarTdDiaCI >= 0
    if (rs.moveToLast() && ok) {
        nama.text = rs.getString(namaCI) //THE ERROR HAPPEN HERE
        umur.text = rs.getString(umrCI)
        jk.text = rs.getString(jkCI)
        data.text = rs.getString(dataCI)
        kadarAu.text = rs.getString(kadarAuCI)
        kadarGd.text = rs.getString(kadarGdCI)
        kadarHb.text = rs.getString(kadarHbCI)
        kadarCh.text = rs.getString(kadarChCI)
        kadarTdSis.text = rs.getString(kadarTdSisCI)
        kadarTdDia.text = rs.getString(kadarTdDiaCI)
    } else {
        if (!ok) {
            /* INVALID COLUMN NAME */
        } else {
            /* NO DATA IN CURSOR */
        }
    }
    rs.close()
}
  • 列名已被猜测,因此可能无法反映实际的列名

要进行调试,您可以添加一个断点,例如在行上并在调试模式下运行,然后在调试窗口中检查游标,或者作为替代方法,使用该方法并检查日志,例如,在行和 之间添加行。rs.moveToLast()DatabaseUtilsdumpCursorDatabaseUtils.dumpCursor(rs)val rs = db.rawQuery("SELECT * FROM uProfile", null)rs.moveToLast()

评论

0赞 Lalu Habib Sasiwimba 10/30/2023
我看到,在您给出返回 -1 错误的链接中,因为该列似乎不存在。请帮我写有效的代码或给我一些例子来说明我的条件。我真的很感激
0赞 MikeT 10/30/2023
@LaluHabibSasiwimba重新检查答案,-1 是光标的位置(在第一行之前)。但是,请再次查看答案,不要使用可能合适的硬编码列索引和代码或改进代码的基础。
0赞 Lalu Habib Sasiwimba 10/30/2023
谢谢你的帮助✨。该应用程序运行非常感谢您