Android 在从中访问数据之前,确保 Cursor 已正确初始化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20240249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:30:58  来源:igfitidea点击:

Make sure the Cursor is initialized correctly before accessing data from it

androidandroid-sqlite

提问by dasdasd

Im trying to get data from my DB.

我试图从我的数据库中获取数据。

This is my code:

这是我的代码:

String[] columns = new String[] {COLUMN_FACEBOOK_ALBUM_COVER, COLUMN_FACEBOOK_ALBUM_IS_ACTIVE};

        String whereClause = COLUMN_FACEBOOK_ALBUM_IS_ACTIVE + "= '" + 1 + "'";

        Cursor cAlbum = ourDatabase.query(TABLE_FACEBOOK, columns, whereClause,null, null, null, null);

        columns = new String[] {COLUMN_FACEBOOK_BIG_IMAGE, COLUMN_FACEBOOK_IMAGE_IS_ACTIVE};

        whereClause = COLUMN_FACEBOOK_IMAGE_IS_ACTIVE + "= '" + 1 + "'";

        Cursor cImage = ourDatabase.query(TABLE_FACEBOOK_IMAGES, columns, null,null, null, null, null);

        String[] list = new String[cAlbum.getCount()+cImage.getCount()];

        int p = 0;

        if(cAlbum.getCount() < 1 && cImage.getCount() < 1)
        {
            cAlbum.close();
            cImage.close();
            return null;
        }

        Log.i("cImage length", cImage.getCount()+"");
        Log.i("cAlbum length", cAlbum.getCount()+"");

        Log.i("list length", list.length+"");

        int i = cImage.getColumnIndex(COLUMN_FACEBOOK_BIG_IMAGE);
        int j = cAlbum.getColumnIndex(COLUMN_FACEBOOK_ALBUM_COVER);

        for (cAlbum.moveToFirst(); !cAlbum.isAfterLast(); cAlbum.moveToNext())
        {
            list[p] = cAlbum.getString(j);
            p++;
        }

        for (cImage.moveToFirst(); !cImage.isAfterLast(); cImage.moveToNext())
        {
            list[p] = cImage.getString(i);
            Log.i("image length", list[p].length()+"");
            p++;
        }

        cAlbum.close();
        cImage.close();

        return list;

The code fails on this line:

代码在这一行失败:

list[p] = cImage.getString(i);

The error message is:

错误信息是:

11-27 12:34:59.683: E/CursorWindow(6901): Failed to read row 2, column 0 from a CursorWindow which has 2 rows, 2 columns.
11-27 12:34:59.683: D/AndroidRuntime(6901): Shutting down VM
11-27 12:34:59.683: W/dalvikvm(6901): threadid=1: thread exiting with uncaught exception (group=0x41e9b930)
11-27 12:34:59.693: E/AndroidRuntime(6901): FATAL EXCEPTION: main
11-27 12:34:59.693: E/AndroidRuntime(6901): java.lang.RuntimeException: Unable to create service com.example.imageswidget.WidgetService: java.lang.IllegalStateException: Couldn't read row 2, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.app.ActivityThread.handleCreateService(ActivityThread.java:2667)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.app.ActivityThread.access00(ActivityThread.java:153)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1329)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.os.Looper.loop(Looper.java:137)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.app.ActivityThread.main(ActivityThread.java:5227)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at java.lang.reflect.Method.invokeNative(Native Method)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at java.lang.reflect.Method.invoke(Method.java:511)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at dalvik.system.NativeStart.main(Native Method)
11-27 12:34:59.693: E/AndroidRuntime(6901): Caused by: java.lang.IllegalStateException: Couldn't read row 2, col 0 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.database.CursorWindow.nativeGetString(Native Method)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.database.CursorWindow.getString(CursorWindow.java:434)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at com.example.imageswidget.DataBaseMain.getFacebookImagesForWidget(DataBaseMain.java:943)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at com.example.imageswidget.WidgetService.onCreate(WidgetService.java:51)
11-27 12:34:59.693: E/AndroidRuntime(6901):     at android.app.ActivityThread.handleCreateService(ActivityThread.java:2657)
11-27 12:34:59.693: E/AndroidRuntime(6901):     ... 10 more

For the call log

对于通话记录

Log.i("image length", list[p].length()+"");

I get few calls before the code breaks. The problem seems to happen only for some rows but the error code does not tell me what the problem is.

在代码中断之前我很少接到电话。问题似乎只发生在某些行上,但错误代码并没有告诉我问题是什么。

Thanks for helping.

谢谢你的帮助。

回答by Oladipo Olasemo

In my case it was because I didn't include the column in the projection passed into the CursorLoader constructor. Which means I was trying to access data from a column that didn't exist in the cursor that was returned.

就我而言,这是因为我没有在传递给 CursorLoader 构造函数的投影中包含该列。这意味着我试图从返回的游标中不存在的列访问数据。

I hope this helps somebody...

我希望这可以帮助某人...

回答by Peter

I have encountered this same exception before. In my case the cause was a database cell containing too much data (a huge string). Judging from the code (COLUMN_FACEBOOK_BIG_IMAGE) I guess that you have encountered the same problem. For the solution was to check the size of the strings that were put into the DB (and down scaling the image when needed). Hope this helps!

我以前遇到过同样的异常。在我的情况下,原因是包含太多数据(一个巨大的字符串)的数据库单元格。从代码(COLUMN_FACEBOOK_BIG_IMAGE)来看,我猜你也遇到了同样的问题。解决方案是检查放入数据库的字符串的大小(并在需要时缩小图像)。希望这可以帮助!

回答by okarakose

Maybe you are using your old database. If you changed some tables, fields on your database and you are now trying on another device (which is you already installed your application before database changes), you should only delete your old database and create new file.

也许您正在使用旧数据库。如果您更改了数据库中的某些表、字段,而您现在正在另一台设备上尝试(即您在数据库更改之前已经安装了应用程序),您应该只删除旧数据库并创建新文件。

回答by Niharika Gautam

You should fix this to solve the following error message

您应该修复此问题以解决以下错误消息

Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.

无法从 CursorWindow 读取第 0 行、第 -1 行。在访问 Cursor 中的数据之前,确保它已正确初始化。

It works in my code.

它适用于我的代码。

  1. Try to position cursor by moveToFirstbefore reading data from it.

  2. Check for null-> if (c != null && c.moveToFirst()) {}

  3. Check for count-> (c != null && c.getCount() >0 && c.moveToFirst()){}

  1. moveToFirst在从中读取数据之前尝试定位光标。

  2. 检查空值-> if (c != null && c.moveToFirst()) {}

  3. 检查计数-> (c != null && c.getCount() >0 && c.moveToFirst()){}

回答by appoll

Try calling cursor.moveToFirst ()before using the cursor. Let me know if that worked.

cursor.moveToFirst ()在使用游标之前尝试调用。让我知道这是否有效。

回答by Neon Warge

I have similar answer as Oladipo Olasemo but happens to me for v-tables and how I was able to fix it. I believe this is the best post to share my experience with this error especially dealing with FTS3 virtual tables, well at least in my case. There are a lot of question regarding this and OP's original question is too generic so here is my take on this question.

我和 Oladipo Olasemo 有类似的答案,但我遇到了 v-tables 以及我是如何修复它的。我相信这是分享我对这个错误尤其是处理 FTS3 虚拟表的经验的最佳帖子,至少在我的情况下是这样。关于这个问题有很多问题,OP 的原始问题太笼统了,所以这是我对这个问题的看法。

I encountered this error due to some restrictions in virtual table consider this one:

由于虚拟表中的一些限制,我遇到了这个错误,考虑这个:

create virtual table V1 using FTS3 (content="MyTable", content1, content2); 

When I search for a specific keyword base on content1 or content2, I realize I was making a query base on the virtual table via this query:

当我根据 content1 或 content2 搜索特定关键字时,我意识到我正在通过以下查询基于虚拟表进行查询:

select * from V1 where V1 match 'hello'

Since this is a virtual table I missed that, it will project the result set according to how you constructed the v-table itself. So it will have columns only for content1 and content2.

由于这是我错过的虚拟表,它将根据您构建 v-table 本身的方式来投影结果集。所以它将只有 content1 和 content2 的列。

I am developing an android app which queries from search results and upon selecting an item from the result set, my backend processing process the selected item and queries for an information that does not exist from the column set. Thus, giving me this error.

我正在开发一个 android 应用程序,它从搜索结果中查询并从结果集中选择一个项目,我的后端处理处理所选项目并查询列集中不存在的信息。因此,给了我这个错误。

The way I solved this, though not so brilliant, is to querythe result from the v-table to get the id for each item, which it always has. Then I construct a query string base from the result ids I acquired then use that to retrieve the necessary data with the projection I required. I got an idea from this question

我解决这个问题的方法虽然不是那么好,是从 v-table 查询结果以获取每个项目的 id,它总是有的。然后我从我获得的结果 ID 构建一个查询字符串库,然后使用它来检索我需要的投影所需的数据。我从这个问题中得到了一个想法

I believe there are lot more ways to encounter this error. I spent almost an hour figuring out what might have caused this. For me, the error projected on the log is not very helpful. It really helps if you really know how data flows within your app.

我相信有更多方法可以遇到此错误。我花了将近一个小时弄清楚可能导致这种情况的原因。对我来说,日志上投射的错误不是很有帮助。如果您真的了解数据在应用程序中的流动方式,那真的很有帮助。

回答by Boban S.

Initialize cursors in database transaction.

在数据库事务中初始化游标。

Cursor cAlbum = null, cImage = null;
db.beginTransaction();
try {
    // init cursors
    cAlbum = db.query(...);
    cImage = db.query(...);
} catch(SQLException e) {
    e.printStackTrace();
} finally {
    db.endTransaction();
}

Check if cursors are not null.

检查游标是否不为空。

if(cAlbum != null && cImage != null) {
    while(cAlbum.moveToNext()) {
        // get data from cAlbum and do what you need
    }
    while(cImage.moveToNext()) {
        // get data from cImage and do what you need
    }

    cAlbum.close();
    cImage.close();
}