I have a cursor returned on an onLoadFinished
callback (from LoaderManager.LoaderCallbacks
), and I want to do some (possibly costly) post-processing on this cursor. So, I'm firing off an AsyncTask
that uses this Cursor. However, I'm getting intermittent crashes with this exception:
android.database.StaleDataException: Attempted to access a cursor after it has been closed.
My suspicion is that this is happening because the cursor (being managed by the Loader in the UI Thread) is being closed before the background thread is finished with it, since this is a managed cursor. Here is some paraphrased code:
private class LoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public void onCreateLoader(int d, Bundle args) {
return new CursorLoader(context, uri, projection, selection, selectionArgs, sortOrder);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
processCursor(cursor)
}
}
private void processCursor(final Cursor cursor) {
new AsyncTask<Void, Void, Result> {
@Override
Result doInBackground(Void... params) {
while(cursor.isAfterLast() == false) {
// doing some costly things with cursor
}
}
}.execute();
}
Is it possible to either,
Somehow flag the cursor to prevent it from being closed from the UI thread.
Notify the manager that the cursor is still in use.
Clone it so that the cloned instance doesn't get closed by the manager.
Another, even better, solution?
Having this post-processing done on the UI thread is absolutely not an option, however, as it can be very costly.
CursorLoader
and make the initial query + the expensive processing in theAsyncTask
. – Jacquez