Using the cursor returned from LoaderManager in AsyncTask

I have a cursor returned by the onLoadFinished (from LoaderManager.LoaderCallbacks ), and I want to do some (possibly expensive) post-processing on this cursor. So, I am AsyncTask , which uses this Cursor. However, I get intermittent crashes with this exception:

 android.database.StaleDataException: Attempted to access a cursor after it has been closed. 

I suspect this is because the cursor (controlled by the loader in the UI thread) closes before the background thread completes it, since it is a controlled cursor. Here is some paraphrase 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 that

  • Somehow mark the cursor so that it does not close from the user interface stream.

  • Inform the manager that the cursor is still in use.

  • Clone it so that the cloned instance is not closed by the manager.

  • Another, even better solution?

However, this post-processing performed in the user interface thread is absolutely not an option, as it can be very expensive.

+6
java android cursor android-loadermanager
source share
2 answers

Is it possible to mark the cursor in some way so that it is not closed from the user interface thread?

No (well, without rewriting the internal APIs).

Is it possible to notify the manager that the cursor is still in use?

Same answer as above.

Is it possible to clone it so that the cloned instance is not closed by the manager?

It sounds messy ... and there is still a chance that the LoaderManager will close the cursor before you can complete its cloning.

Is there a better solution?

Yes. Request a new cursor instead of reusing the one you pass to LoaderManager .

+2
source share

Man, I faced the same problem. The method is to cancel the asynthesis in the onDestroy method.

 private YourAsyncTask asyncTask @Override protected void onDestroy(){ super.onDestroy(); asyncTask.cancel(true); } 
0
source share

All Articles