Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make my Cursor survive an orientation change?

I am trying to make my app rotation friendly, but I am having some problems saving the cursor.

The cursor holds about 13k+ rows of data displayed in a ListView, and thus would take quite a while if I would do a requery every time the configuration changes. In my onRetainNonConfigurationInstance(), I am returning my Cursor and then retrieving it through getLastNonConfigurationInstance().

However, my retrieved cursor seems to be closed already, and thus my adapter cannot render the list anymore. From what I understand, the cursor was closed since onDestroy() automatically closes all cursors.

I save the Cursor like this:

@Override
public Object onRetainNonConfigurationInstance() {
    return myCursor;
}

And retrieve it like this:

myCursor = (Cursor)getLastNonConfigurationInstance();
if (myCursor == null) {
    // Do some stuff here (access DB, etc)
} else { // we are returning from configuration change
    // Feed the cursor to the adapter
}

I am pasting the stack trace if someone wants to look at it:

01-25 16:57:45.637: ERROR/AndroidRuntime(12976): android.database.StaleDataException: Access closed cursor
    01-25 16:57:45.637: ERROR/AndroidRuntime(12976):     at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:217)
    01-25 16:57:45.637: ERROR/AndroidRuntime(12976):     at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:41)
    01-25 16:57:45.637: ERROR/AndroidRuntime(12976):     at com.test.sample.helper.DictionaryAdapter.bindView(DictionaryAdapter.java:35)
[........More ListView-related errors here..........]

I stepped through the code and I found out that as far as onRetainNonConfigurationInstance(), the cursor is still open, but after getting it through getLastNonConfigurationInstance() it is already closed.

How can I make my Cursor survive the orientation change? Thank you for the help!

EDIT: Based on Romain's answer, I commented out all my startManagingCursor()s. I should have connected the dots and thought about it! Anyway, my app now survives one rotation, but flipping it back to the original orientation still crashes it. Continuing my debugging and will let you know what I find out.

EDIT2: I think I may have found what is causing the new errors. I have implemented a FilterQueryProvider which returns a new Cursor. What I did was assign the results of that filter to my original Cursor. Seems to work so far.

like image 740
Zarah Avatar asked Jan 25 '11 09:01

Zarah


1 Answers

You are probably using a managed cursor. Managed cursors are automatically closed when the Activity is destroyed. You should switch to an unmanaged Cursor.

like image 107
Romain Guy Avatar answered Sep 21 '22 15:09

Romain Guy