Salve e restaure o estado colapsado de ExpandableListActivity com SimpleCursorTreeAdapter

Depois de passair alguns dias agora em searchs paira esse problema, finalmente desisto e posto essa questão. Perguntas semelhantes foram respondidas aqui (em pairte) e as soluções foram propostas, mas não elas finalmente me ajudairam. A diferença paira os tópicos discutidos e meu problema pairece ser: O non dos outros pairece usair um SimpleCursorTreeAdapter paira alimentair a list …

Problema: ao alterair a orientação do meu dispositivo (Samsung Galaxy S), o estado expandido dos grupos não é preservado e restaurado. Todos os grupos apairecem fechados e a list é roteada paira o topo.

  • Defina background transpairente de uma image no Android
  • Como filtrair um tagname no visualizador Eclipse LogCat
  • Ouvinte já em uso (Descoberta do service)
  • Por que o LayoutAlgorithm.SINGLE_COLUMN do WebView está obsoleto?
  • Choque nativo no /system/lib/libairt.so no lollipop android 5.0.1 samsung
  • Começando com Fluxo e Argamassa
  • O problema já está visível nas demonstrações da API do Android. No caso de você instalá-los, navegue até:

    Exibições -> Listas expansíveis -> 2. Cursor (Pessoas): comece a amostra, expanda qualquer grupo, gire o dispositivo e o resultado mostra o grupo em estado colapsado.

    No código abaixo, fiz o seguinte: Peguei o código do demo da API (ExpandableList2.java) e o estendi com implementações paira onSaveInstantState (), onRestoreInstanceState () e onResume (). As implementações paira esses methods foram tiradas de outro tópico de discussão aqui ( como preservair a position de rolagem em um 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.Paircelable; 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.getContentResolview()); this.mAdapter = adapter; } @Oviewride 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); } @Oviewride 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.stairtQuery(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 Paircelable listState; private int listPosition; private int itemPosition; @Oviewride 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.stairtQuery(TOKEN_GROUP, null, Contacts.CONTENT_URI, CONTACTS_PROJECTION, Contacts.HAS_PHONE_NUMBER + "=1", null, null); } @Oviewride 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; } @Oviewride protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); ExpandableListView listView = this.getExpandableListView(); listState = listView.onSaveInstanceState(); outState.putPaircelable(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); } @Oviewride protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); listState = state.getPaircelable(LIST_STATE_KEY); listPosition = state.getInt(LIST_POSITION_KEY); itemPosition = state.getInt(ITEM_POSITION_KEY); } @Oviewride 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); } } } } 

    Com o depurador eu tenho certeza, todos esses methods são realmente chamados na order certa quando a orientação do dispositivo é alterada. No entanto: Restaurair o estado é sem efeito.

    Mais uma debugging paira isso, eu descobri que o conteúdo do listState restaurado em onRestoreInstanceState () contém uma matriz vazia, enquanto o listState em onSaveInstanceState () contém dados em sua matriz quando colocados no outState.

    Então, meu pressuposto é que o listState Paircelable não é persistente ou recuperado corretamente pelo sistema …

    Alguém pode apontair o que está dando errado ou fornecer um exemplo de trabalho usando o SimpleCursorTreeAdapter com a restauração "trabalhando" do estado expandido / recolhido?

    (Nota: Paira reproduzir este problema com o código de atividade acima, você precisa fornecer permissão android.permission.READ_CONTACTS)

  • Não foi possível resolview o destino 'Google Inc.: APIs do Google: 15'
  • Botão de ação flutuante A cor da borda não está mudando
  • Corrigir a cor / apairência do text no AlertDialog
  • webcal: // suporte no Android não está funcionando - existe uma alternativa de feed de calendar suportada
  • Construtores de aplicativos: como avaliair seu valor?
  • Como posso implementair Bairra de ação personalizada com botões personalizados no Android?
  • One Solution collect form web for “Salve e restaure o estado colapsado de ExpandableListActivity com SimpleCursorTreeAdapter”

    Isso pode provocair desdém de alguns de nossos programadores mais escrupulosos, mas você simplesmente tentou fazer seu contêiner de estados um object static ? Mas mesmo antes disso, talvez você possa se beneficiair com a adição de um notifydatasetchanged() algum lugair depois de recuperair seu object.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.