无法分配 CursorWindow

19

我在我的安卓应用中操作一个SQLite3数据库。我刚刚从已预置的数据库中读取了200k行和14列的内容。每个条目都是单词,所有列的数据类型均为文本。查询长度不超过11个字母的单词(如ABANDONMENT)能够正常工作。但对于12个或更多字母的单词(如ABANDONMENTS),应用程序会崩溃。以下是日志:

Could not allocate CursorWindow '//data//data//com.example.myapp//databases//database.sqlite' of size 2097152 due to error -12.
threadid=11: thread exiting with uncaught exception (group=0x40adf9f0)
FATAL EXCEPTION: Thread-2883
android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=861 (# cursors opened by this proc=861)
at android.database.CursorWindow.<init>(CursorWindow.java:104)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:162)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:156)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:161)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:201)
at com.example.myapp.MainActivity.query(MainActivity.java:815)
at com.example.myapp.MainActivity$2.run(MainActivity.java:356)
at java.lang.Thread.run(Thread.java:856)

代码:

query = "select * from words where col_1 = \"" + (myWord)+ "\";";
cursor = database.rawQuery(query, null);
if (cursor != null)                                          
    cursor.moveToFirst(); // line 815
if (!cursor.isAfterLast()) {
    do {
        for (i = 1; i < cursor.getColumnCount(); i++) {
            temp = cursor.getString(i);
            //other stuff
        }
    } while (cursor.moveToNext());
    cursor.close();
}

出错信息的含义是什么,为什么应用程序会崩溃?


1
完整的代码会很有帮助。您在自己管理游标后是否关闭了它,为什么不直接调用cursor.moveToNext()而不是!cursor.isAfterLast()? - Mushtaq Jameel
完整的应用程序代码有1000行。cursor.isAfterLast用于检查游标是否已经遍历了所有结果,如果是,则可以停止。 - Frozen Crayon
你是否在 while 循环内关闭了游标? - Mushtaq Jameel
没有。我忘记把那行代码粘贴到上面了。 - Frozen Crayon
3个回答

27

错误-12表示游标泄漏。

尝试关闭它:

try {....} finally {  cursor.close();}

我使用 Kotlin 的 use 方法,它会自动关闭所有内容,所以不是这个问题。 - user924

16

我在一个循环中进行查询。将游标关闭放在循环内而不是外部解决了这个问题。


7

Android 游标将查询结果读入内存,并且该数据的限制为1 MB。

之所以选择此限制,是因为这么多的数据可能会使您的应用在移动设备上运行缓慢。

如果可能,您应该:

  • 不要在代码中进行计算,而是在 SQL 中进行;
  • 仅查询您需要的数据(即不使用 SELECT *,而是获取您需要的列,并使用 WHERE 过滤器);
  • 以较小的部分读取数据。

这是不可能的。表中的所有行都是唯一的。因此,查询只会返回单个结果。 - Frozen Crayon
你肯定会得到不止一条记录。相当于 SELECT COUNT(*) ... 的结果是什么? - CL.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接