SQLiteBlobTooBigException:行太大,无法放入 CursorWindow requiredPos=0,totalRows=1

Posted

技术标签:

【中文标题】SQLiteBlobTooBigException:行太大,无法放入 CursorWindow requiredPos=0,totalRows=1【英文标题】:SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos=0, totalRows=1 【发布时间】:2019-01-28 07:22:02 【问题描述】:

我只在 android 9 中遇到异常,重新安装后一切看起来都很好,

例外:

android.database.sqlite.SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos=0, totalRows=1...

代码:

Cursor cursor = database.query(......);
    if(cursor == null || cursor.getCount() < 0)  //Here is the error
        Log.d("Error", "count : null");
        return "";
    

已编辑:

java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:354)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)

Caused by: android.database.sqlite.SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos=0, totalRows=1
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:859)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:149)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:137)

提前谢谢大家

【问题讨论】:

您能否编辑您的问题以显示完整的堆栈跟踪,而不仅仅是堆栈跟踪中的一行。添加查询也可能有用。 我已经编辑了我的答案,检查一次,@MikeT 您找到解决方案了吗?我遇到了同样的例外@Bikash Sahani。 这种情况曾经发生过,有人在没有卸载我的应用程序的情况下升级到奥利奥并继续使用它,然后这个问题就来了,所以当时我正在放弃桌子并再次创建它 你有什么解决办法吗???我只在 android 9 pocof1 设备中遇到这个问题?在第一次安装中升级到派后,我收到了这个错误。在我重新安装它的工作正常后 【参考方案1】:

这对我有用,你必须把它放在你的主要活动中。

try 
    Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize");
    field.setAccessible(true);
    field.set(null, 100 * 1024 * 1024); //the 100MB is the new size
     catch (Exception e) 
       e.printStackTrace();
    

【讨论】:

这绝对解决了问题,所以谢谢你和+1。快速跟进问题,有谁知道这是否会触发任何级联的外部运行时异常? IE,如果用户的设备上有 【参考方案2】:

试试这个 API 28 以上的new constructor method。也许你应该为 CursorWindow 设置一个有限的 windowSizeBytes 并尝试捕获异常。

相关cts代码(https://android.googlesource.com/platform/cts/+/master/tests/tests/database/src/android/database/sqlite/cts/SQLiteCursorTest.java):

    public void testRowTooBig() 
        mDatabase.execSQL("CREATE TABLE Tst (Txt BLOB NOT NULL);");
        byte[] testArr = new byte[10000];
        Arrays.fill(testArr, (byte) 1);
        for (int i = 0; i < 10; i++) 
            mDatabase.execSQL("INSERT INTO Tst VALUES (?)", new Object[]testArr);
        
        // Now reduce window size, so that no rows can fit
        Cursor cursor = mDatabase.rawQuery("SELECT * FROM TST", null);
        CursorWindow cw = new CursorWindow("test", 5000);
        AbstractWindowedCursor ac = (AbstractWindowedCursor) cursor;
        ac.setWindow(cw);
        try 
            ac.moveToNext();
            fail("Exception is expected when row exceeds CursorWindow size");
         catch (SQLiteBlobTooBigException expected) 
        
    

其他:

自从本文最初发表以来,我们在 Android P 开发者预览版以改进上述行为。这 平台现在允许应用程序禁用窗口启发式的 ⅓ 和 配置 CursorWindow 大小。

参考链接: https://medium.com/androiddevelopers/large-database-queries-on-android-cb043ae626e8

【讨论】:

【参考方案3】:

尝试缩放位图:

Bitmap.createScaledBitmap

【讨论】:

【参考方案4】:

我发现如何使用 length() 和 substr() 只请求 1MB(CursorWindow 的最大值为 2MB),也许它会help。此外,您可以将 context.getContentResolver().query() 与仅包含 _id 列的选择一起使用,这样您就不会加载与其他列相关的数据。

【讨论】:

以上是关于SQLiteBlobTooBigException:行太大,无法放入 CursorWindow requiredPos=0,totalRows=1的主要内容,如果未能解决你的问题,请参考以下文章