I have exactly the same situation:
- main activity is a tabbed activity
- the tab activities are all ExpandableListActivity
- the ExpandableListActivity is using a class that
extends CursorTreeAdapter to provide the data to display
- if one group is expanded and if onStop() is called in the main
activity, the app force closes with the same exception andfan22 reported
- works well on Android up to 2.3.3, breaks on Honeycomb
I tried a lot to make it work but I don't want to bore you with unnecessary
details. Here's what worked for me in the end:
A class extending CursorTreeAdapter has to overwrite "protected Cursor
getChildrenCursor(Cursor groupCursor)".
It returns the Cursor to populate the children of the tree view. The
documentation explicitly says that you have to manage the cursor:
"It is your responsibility to manage this Cursor through the Activity
lifecycle".
Therefore you would write the code along those lines:
@Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
long groupID = groupCursor.getLong(groupCursor.getColumnIndex("_id"));
Cursor childCursor = database.getList(groupID);
activity.startManagingCursor(childCursor);
return childCursor;
}
When I replaced "return childCursor;" with "return null;" everything went
back to normal (except that the view wasn't populated of course) which means
that this piece of code was causing the problems.
Just out of curiosity and because I ran out of ideas I removed
the activity.startManagingCursor(childCursor); preventing the cursor from
being actively managed.
I didn't expect it to work and furthermore expected some
DatabaseObjectNotClosedException to be thrown. Here's what happened:
- Honeycomb: worked like a charm
- 2.33: worked like a charm
- 2.21: worked in general but a lot
of DatabaseObjectNotClosedException in logcat
Conclusion: I'm pretty sure I'm not doing anything incorrect/illegal and
rather think that the manage cursor code in Honeycomb is broken somehow
(maybe due to the fact that they replaced it with the CursorLoader).
My solution to make it work on all above mentioned Android versions (I will
test it on other versions too and will report back if it shouldn't work on
those) is to write my own startManagingCursor() method which is fairly easy
(I checked the Android's source code and it doesn't really do anything
different than I'm doing, haven't checked the Honeycomb code though):
private ArrayList<Cursor> managedCursors = new ArrayList<Cursor>();
@Override
public void startManagingCursor(Cursor c) {
synchronized(managedCursors) {
if (!managedCursors.contains(c)) managedCursors.add(c);
}
}
@Override
public void stopManagingCursor(Cursor c) {
synchronized(managedCursors) {
managedCursors.remove(c);
}
}
private void destroyManagedCursors() {
synchronized(managedCursors) {
for (Cursor c:managedCursors) {
c.close();
}
}
}
destroyManagedCursors() obviously should be called in the activity's
onDestroy() method.
Hope that helps
Emanuel Moecklin
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en