Cursor.moveToNext 错误
Cursor.moveToNext error
我偶尔会看到崩溃报告:
Fatal Exception: java.lang.IllegalStateException: Couldn't read row 1127, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(CursorWindow.java)
at android.database.CursorWindow.getLong(CursorWindow.java:511)
at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:220)
at android.database.AbstractCursor.moveToNext(AbstractCursor.java:245)
at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)
at com.anthonymandra.util.ImageUtils.cleanDatabase(SourceFile:381)
显然 moveToNext
在循环中失败(注意第 1127 行)。该循环会删除表示无法再找到的文件的条目。
final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
try( Cursor cursor = c.getContentResolver().query(Meta.CONTENT_URI, null, null, null, null))
{
if (cursor == null)
return;
final int uriColumn = cursor.getColumnIndex(Meta.URI);
final int idColumn = cursor.getColumnIndex(BaseColumns._ID);
while (cursor.moveToNext())
{
String uriString = cursor.getString(uriColumn);
if (uriString == null) // we've got some bogus data, just remove
{
operations.add(ContentProviderOperation.newDelete(
Uri.withAppendedPath(Meta.CONTENT_URI, cursor.getString(idColumn))).build());
continue;
}
Uri uri = Uri.parse(uriString);
UsefulDocumentFile file = UsefulDocumentFile.fromUri(c, uri);
if (!file.exists())
{
operations.add(ContentProviderOperation.newDelete(Meta.CONTENT_URI)
.withSelection(getWhere(), new String[]{uriString}).build());
}
}
}
c.getContentResolver().applyBatch(Meta.AUTHORITY, operations);
知道游标怎么会像那样在循环中失败吗?
可能是你在数据库中的 srote 文件,这就是你得到 java.lang.IllegalStateException
的原因
UsefulDocumentFile file = UsefulDocumentFile.fromUri(c, uri);
Android SQLite returns 游标 windows 中指定的最大大小为 2MB 的行
config_cursorWindowSize。如果您的行超过此限制,您将收到此错误。
在文件系统中存储文件,在数据库中存储路径。
您似乎在进行相当大的查询:至少 1127 行和所有可能的列(尽管您只使用了其中的两列)。而且,在你使用 Cursor
的过程中,你正在做磁盘 I/O and/or IPC 回到 ContentProvider
,假设 UsefulDocumentFile
与 [=38] 相关=]的DocumentFile
.
正如 Prakash 指出的那样,您返回的 Cursor
可能只包含信息的一个子集。一旦您尝试前进超过该点,Cursor
就需要返回数据源并获取下一个 window 结果。如果在这项工作进行期间数据发生重大变化(例如,现在少于 1127 行),我可以看到你 运行 遇到此类问题。
我建议你:
将您返回的列限制为您需要的子集,并且
避免在循环中使用 I/O(例如,旋转 Cursor
以构建 ArrayList<Pair>
或其他东西,关闭 Cursor
, 然后遍历列表)
我偶尔会看到崩溃报告:
Fatal Exception: java.lang.IllegalStateException: Couldn't read row 1127, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(CursorWindow.java)
at android.database.CursorWindow.getLong(CursorWindow.java:511)
at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:220)
at android.database.AbstractCursor.moveToNext(AbstractCursor.java:245)
at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)
at com.anthonymandra.util.ImageUtils.cleanDatabase(SourceFile:381)
显然 moveToNext
在循环中失败(注意第 1127 行)。该循环会删除表示无法再找到的文件的条目。
final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
try( Cursor cursor = c.getContentResolver().query(Meta.CONTENT_URI, null, null, null, null))
{
if (cursor == null)
return;
final int uriColumn = cursor.getColumnIndex(Meta.URI);
final int idColumn = cursor.getColumnIndex(BaseColumns._ID);
while (cursor.moveToNext())
{
String uriString = cursor.getString(uriColumn);
if (uriString == null) // we've got some bogus data, just remove
{
operations.add(ContentProviderOperation.newDelete(
Uri.withAppendedPath(Meta.CONTENT_URI, cursor.getString(idColumn))).build());
continue;
}
Uri uri = Uri.parse(uriString);
UsefulDocumentFile file = UsefulDocumentFile.fromUri(c, uri);
if (!file.exists())
{
operations.add(ContentProviderOperation.newDelete(Meta.CONTENT_URI)
.withSelection(getWhere(), new String[]{uriString}).build());
}
}
}
c.getContentResolver().applyBatch(Meta.AUTHORITY, operations);
知道游标怎么会像那样在循环中失败吗?
可能是你在数据库中的 srote 文件,这就是你得到 java.lang.IllegalStateException
UsefulDocumentFile file = UsefulDocumentFile.fromUri(c, uri);
Android SQLite returns 游标 windows 中指定的最大大小为 2MB 的行 config_cursorWindowSize。如果您的行超过此限制,您将收到此错误。
在文件系统中存储文件,在数据库中存储路径。
您似乎在进行相当大的查询:至少 1127 行和所有可能的列(尽管您只使用了其中的两列)。而且,在你使用 Cursor
的过程中,你正在做磁盘 I/O and/or IPC 回到 ContentProvider
,假设 UsefulDocumentFile
与 [=38] 相关=]的DocumentFile
.
正如 Prakash 指出的那样,您返回的 Cursor
可能只包含信息的一个子集。一旦您尝试前进超过该点,Cursor
就需要返回数据源并获取下一个 window 结果。如果在这项工作进行期间数据发生重大变化(例如,现在少于 1127 行),我可以看到你 运行 遇到此类问题。
我建议你:
将您返回的列限制为您需要的子集,并且
避免在循环中使用 I/O(例如,旋转
Cursor
以构建ArrayList<Pair>
或其他东西,关闭Cursor
, 然后遍历列表)