Speichern und Wiederherstellen des zusammengefallenen Zustands von ExpandableListActivity mit SimpleCursorTreeAdapter

Nachdem ich einige Tage hier auf die Forschung für dieses Problem verbracht habe, gebe ich endlich auf und stelle diese Frage vor. Ähnliche Fragen wurden hier beantwortet (teilweise) und Lösungen wurden vorgeschlagen, aber nicht von ihnen schließlich half mir. Der Unterschied zu den besprochenen Themen und meinem Problem scheint zu sein: Nicht von den anderen scheint ein SimpleCursorTreeAdapter zu verwenden, um die Liste zu füttern …

Problem: Beim Ändern der Ausrichtung meines Geräts (Samsung Galaxy S) wird der Erweiterungszustand der Gruppen nicht erhalten und wiederhergestellt. Alle Gruppen werden geschlossen und die Liste wird nach oben gescrollt.

  • Warum ist der Android-Handy-Simulator so langsam?
  • Override Heim und Back-Taste ist Fall ein Boolescher ist wahr
  • Android: EditText verliert Inhalt beim Scrollen in ListView?
  • Erweiterbare Listenindikator
  • Paket com.google.zxing fehlt in Zxing Barcode-Bibliothek für Android
  • Recycler anzeigen Scrollbar anzeigen
  • Das Problem ist bereits in den AndroidAPI-Demos sichtbar. Falls sie installiert sind, navigieren Sie zu:

    Views -> Expandable Lists -> 2. Cursor (People): Starten Sie das Sample, erweitern Sie jede Gruppe, schalten Sie Ihr Gerät und das Ergebnis zeigt die Gruppe im zusammengefalteten Zustand.

    In dem unten stehenden Code habe ich folgendes getan: Den Code aus der API-Demo (ExpandableList2.java) genommen und mit Implementierungen für onSaveInstantState (), onRestoreInstanceState () und onResume () erweitert. Implementierungen für diese Methoden wurden aus einem weiteren Diskussions-Thread hier genommen ( wie man die Scroll-Position in einem ExpandableListView beibehalten kann ).

    import android.app.ExpandableListActivity; import android.content.AsyncQueryHandler; import android.content.ContentUris; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Contacts; import android.view.View; import android.widget.CursorTreeAdapter; import android.widget.ExpandableListView; import android.widget.SimpleCursorTreeAdapter; public class MainActivity extends ExpandableListActivity { private static final String LIST_STATE_KEY = "levelSelectListState"; private static final String LIST_POSITION_KEY = "levelSelectListPosition"; private static final String ITEM_POSITION_KEY = "levelSelectItemPosition"; private static final String[] CONTACTS_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME }; private static final int GROUP_ID_COLUMN_INDEX = 0; private static final String[] PHONE_NUMBER_PROJECTION = new String[] { Phone._ID, Phone.NUMBER }; private static final int TOKEN_GROUP = 0; private static final int TOKEN_CHILD = 1; private static final class QueryHandler extends AsyncQueryHandler { private CursorTreeAdapter mAdapter; public QueryHandler(Context context, CursorTreeAdapter adapter) { super(context.getContentResolver()); this.mAdapter = adapter; } @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { switch (token) { case TOKEN_GROUP: mAdapter.setGroupCursor(cursor); break; case TOKEN_CHILD: int groupPosition = (Integer) cookie; mAdapter.setChildrenCursor(groupPosition, cursor); break; } } } public class MyExpandableListAdapter extends SimpleCursorTreeAdapter { // Note that the constructor does not take a Cursor. This is done to // avoid querying the // database on the main thread. public MyExpandableListAdapter(Context context, int groupLayout, int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom, int[] childrenTo) { super(context, null, groupLayout, groupFrom, groupTo, childLayout, childrenFrom, childrenTo); } @Override protected Cursor getChildrenCursor(Cursor groupCursor) { // Given the group, we return a cursor for all the children within // that group // Return a cursor that points to this contact's phone numbers Uri.Builder builder = Contacts.CONTENT_URI.buildUpon(); ContentUris.appendId(builder, groupCursor.getLong(GROUP_ID_COLUMN_INDEX)); builder.appendEncodedPath(Contacts.Data.CONTENT_DIRECTORY); Uri phoneNumbersUri = builder.build(); mQueryHandler.startQuery(TOKEN_CHILD, groupCursor.getPosition(), phoneNumbersUri, PHONE_NUMBER_PROJECTION, Phone.MIMETYPE + "=?", new String[] { Phone.CONTENT_ITEM_TYPE }, null); return null; } } private QueryHandler mQueryHandler; private CursorTreeAdapter mAdapter; private Parcelable listState; private int listPosition; private int itemPosition; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Set up our adapter mAdapter = new MyExpandableListAdapter( this, android.R.layout.simple_expandable_list_item_1, android.R.layout.simple_expandable_list_item_1, new String[] { Contacts.DISPLAY_NAME }, // Name for group // layouts new int[] { android.R.id.text1 }, new String[] { Phone.NUMBER }, // Number for child layouts new int[] { android.R.id.text1 }); setListAdapter(mAdapter); mQueryHandler = new QueryHandler(this, mAdapter); // Query for people mQueryHandler.startQuery(TOKEN_GROUP, null, Contacts.CONTENT_URI, CONTACTS_PROJECTION, Contacts.HAS_PHONE_NUMBER + "=1", null, null); } @Override protected void onDestroy() { super.onDestroy(); // Null out the group cursor. This will cause the group cursor and all // of the child cursors // to be closed. mAdapter.changeCursor(null); mAdapter = null; } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); ExpandableListView listView = this.getExpandableListView(); listState = listView.onSaveInstanceState(); outState.putParcelable(LIST_STATE_KEY, listState); listPosition = listView.getFirstVisiblePosition(); outState.putInt(LIST_POSITION_KEY, listPosition); View itemView = listView.getChildAt(0); itemPosition = itemView == null ? 0 : itemView.getTop(); outState.putInt(ITEM_POSITION_KEY, itemPosition); } @Override protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); listState = state.getParcelable(LIST_STATE_KEY); listPosition = state.getInt(LIST_POSITION_KEY); itemPosition = state.getInt(ITEM_POSITION_KEY); } @Override protected void onResume() { super.onResume(); ExpandableListView listView = this.getExpandableListView(); if (listView != null) { if (listState != null) { // yes, this code is reached listView.onRestoreInstanceState(listState); listView.setSelectionFromTop(listPosition, itemPosition); } } } } 

    Mit dem Debugger habe ich sichergestellt, dass alle diese Methoden eigentlich in der richtigen Reihenfolge aufgerufen werden, wenn die Geräteorientierung geändert wird. Allerdings: Die Wiederherstellung des Staates ist ohne Wirkung.

    Weiterhin entdeckte ich, dass der Inhalt des wiederhergestellten listState in onRestoreInstanceState () ein leeres Array enthält, während das listState in onSaveInstanceState () Daten in seinem Array enthält, wenn es in die outState eingefügt wird.

    Also meine Annahme ist, dass die listState Parcelable nicht beharrt oder korrekt vom System abgerufen wird …

    Kann jemand darauf hinweisen, was falsch läuft oder ein funktionierendes Beispiel mit dem SimpleCursorTreeAdapter mit "arbeitender" Wiederherstellung von expand / collapsed state?

    (Hinweis: Um dieses Problem mit dem oben genannten Aktivitätscode zu reproduzieren, müssen Sie die android.permission.READ_CONTACTS-Berechtigung angeben)

  • Wie mache ich eine lineare Auffüllung?
  • Übergabe von benutzerdefinierten Objekt an Android-Service in verschiedenen Prozess
  • Gesichtserkennung mit android sdk nicht opencv
  • Android: So aktivieren / deaktivieren Sie Wifi oder Internet Connection programmgesteuert
  • Wie kann ich javadoc zu Google Play Services in Android Studio hinzufügen?
  • Was bedeutet es, dass eine Methode abgelehnt wird und wie kann ich die daraus resultierenden Fehler lösen?
  • One Solution collect form web for “Speichern und Wiederherstellen des zusammengefallenen Zustands von ExpandableListActivity mit SimpleCursorTreeAdapter”

    Das könnte sich von einigen unserer gewissenhafteren Programmierern verabschieden, aber hast du einfach versucht, deine Staaten zu einem static Objekt zu machen? Aber noch vorher, vielleicht könnten Sie davon profitieren, dass Sie ein notifydatasetchanged() irgendwo hinzufügen, nachdem Sie Ihr Objekt abgerufen haben.

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.