2012-08-31 13 views
7

Nachdem ich nun einige Tage für dieses Problem Forschung betrieben habe, gebe ich endlich auf und poste diese Frage. Ähnliche Fragen wurden hier (teilweise) beantwortet und Lösungen wurden vorgeschlagen, aber keiner von ihnen hat mir letztendlich geholfen. Der Unterschied zu den diskutierten Themen und mein Problem scheint zu sein: Nicht die andere scheint einen SimpleCursorTreeAdapter zu verwenden, um die Liste zu füttern ...Speichern und Wiederherstellen des minimierten Zustandes von ExpandableListActivity mit SimpleCursorTreeAdapter

Problem: Wenn die Ausrichtung meines Geräts zu ändern (Samsung Galaxy S), Der Erweiterungsstatus der Gruppen wird nicht beibehalten und wiederhergestellt. Alle Gruppen erscheinen geschlossen und die Liste wird nach oben gescrollt. Das Problem ist bereits im Android API-Demos sichtbar. Wenn Sie sie installiert haben, navigieren Sie zu:

Ansichten -> Erweiterbare Listen -> 2. Cursor (Menschen): Starten Sie das Beispiel, erweitern Sie eine beliebige Gruppe, drehen Sie Ihr Gerät und das Ergebnis zeigt die Gruppe im zusammengefalteten Zustand .

Im folgenden Code habe ich Folgendes getan: Ich nahm den Code aus der API-Demo (ExpandableList2.java) und erweiterte ihn mit Implementierungen für onSaveInstantState(), onRestoreInstanceState() und onResume(). Implementierungen für diese Methoden wurden hier einem anderen Diskussionsthread entnommen (How to preserve scroll position in an ExpandableListView).

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 ich sicher gemacht, alle diese Methoden werden als tatsächlich in der richtigen Reihenfolge, wenn die Ausrichtung des Geräts geändert wird. Allerdings: Die Wiederherstellung des Status ist ohne Wirkung.

Weitere Debugging hinein, fand ich, dass der Inhalt des wiederhergestellten listState in onRestoreInstanceState() ein leeres Array enthält, während der listState in onSaveInstanceState() Daten in ihrer Anordnung enthält, wenn in die outstate setzen.

So meine Vermutung ist, dass die listState Parcel nicht beibehalten wird, oder vom System korrekt abgerufen ...

Kann jemand darauf hinweisen, was nicht in Ordnung ist, oder ein funktionsfähiges Beispiel bieten die SimpleCursorTreeAdapter Verwendung mit „arbeiten“ Wiederherstellung des expand/collapsed Zustandes?

(Hinweis: Um dieses Problem mit dem obigen Code Aktivität zu reproduzieren, müssen Sie android.permission.READ_CONTACTS Erlaubnis zur Verfügung zu stellen)

+2

Dies ist eine wohlgeformte Frage! – giZm0

+0

Nach dem Debuggen dieses Problems mehrere Male auf verschiedenen Android-Versionen, gebe ich die direkte Lösung. Ich konnte schließlich nicht herausfinden, warum ** listState ** in onRestoreInstanceState() nicht korrekt ausgefüllt wurde. So, jetzt verwende ich die explizite Lösung beschrieben in http://stackoverflow.com/questions/4184556/save-and-restore-expanded-collapsed-state-of-an-expandablistactivity Dies funktioniert gut für mein Problem . – Michael

Antwort

0

diese Verachtung von einigen unserer sorgfältigen Programmierer ziehen könnte, aber Sie haben einfach versucht, zu machen Ihre Staaten Container ein static Objekt? Aber vielleicht profitieren Sie schon vorher davon, dass Sie nach dem Abrufen Ihres Objekts eine notifydatasetchanged() hinzufügen.

Verwandte Themen