我正在使用 loaderManager 从数据库中加载一些结果。不幸的是,以下代码在旋转设备后产生了 StaleDataException:
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
{
// If we've returned results, then pass them and the webSearches cursor along to be displayed
if(cursor.moveToFirst())
{
// Get a cursor containing additional web searches and merge it at the end of the results cursor
MatrixCursor searchesCursor = getWebSearchesCursor(searchTerm, false);
Cursor[] cursors = { cursor, searchesCursor };
// TODO: Figure out why merging cursors here causes staledataexception after rotation
Cursor results = new MergeCursor(cursors);
// Display the cursor in the ListView
adapter.changeCursor(results);
}
// If no results were returned, then return suggestions for web searches
else
{
// Get a cursor containing additional web searches
MatrixCursor noResults = getWebSearchesCursor(searchTerm, true);
adapter.changeCursor(noResults);
}
// Show the listView and hide the progress spinner
toggleListView(SHOW);
}
调用 getWebSearchesCursor() 会返回一个 MatrixCursor 以及一些附加的搜索提示,以伴随任何返回的结果。我发现将 adapter.changeCursor(results) 更改为 adapter.changeCursor(cursor) 可以修复错误,因此看起来将 MatrixCursor 合并到返回的游标会产生错误。
我的问题是,为什么?
如果返回任何结果,我希望能够向返回的游标添加其他项目,以便用户可以选择在几个网站上执行搜索。有没有更好的方法来合并游标,以便在旋转后不会出现此异常?
最佳答案
如果您已经开始在所有地方使用 swapCursor()
而不是 changeCursor()
,那么我希望您也已经开始在这些地方处理游标关闭。
changeCursor()
将关闭旧游标,这是有意为之的,当您直接使用 onLoadFinished()
提供的游标时可以完美地工作。它以这种方式完成,因此您不必担心关闭它。
当您旋转设备时,android 系统会检查上次发送给您的光标是否尚未关闭,然后再次发送,而不是花费资源创建一个新的。您的代码将此光标包装在 MergeCursor
的新实例中,该实例被传递给 changeCursor()
,它会发现这不是同一个对象它之前得到,并决定关闭旧实例。由于 MergeCursor
仅包装您传递给它的游标,而不是复制其中的数据,因此您的新实例现在(至少)包含一个关闭的游标。
要正确处理这个问题,您需要自己编写一些代码来检查您通过 onLoadFinished()
获得的光标是否与您当前的 MergeCursor 中的光标相同
实例,并且只有在获得新游标时才关闭现有实例。当然,您还需要跟踪包含在同一 MergeCursor
实例中的其他游标。
关于android - 在 onLoadFinished() 期间合并游标会在旋转后导致 StaleDataException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16392692/