web-dev-qa-db-fra.com

RecyclerView stocker / restaurer l'état entre les activités

Je migre mes ListViews vers RecyclerViews. Avec listviews j'ai utilisé la technique courante décrite ici pour stocker et restaurer la position de défilement entre les activités.

Comment faire la même chose avec RecyclerViews? les RecyclerView.onSaveInstanceState() semblent avoir un accès protected et ne peuvent donc pas être utilisés directement.

61
khusrav

Ok, alors répondez à ma propre question. Si j'ai bien compris, étant donné qu'ils ont découplé le code de présentation et le code de recyclage de la vue (ainsi le nom), le composant responsable de la conservation de l'état de la présentation (et de sa restauration) est désormais le LayoutManager utilisé dans votre vue recyclée. .

Ainsi, pour stocker l’état, vous utilisez le même modèle, mais sur le gestionnaire d’agencement et non le recyclerview:

protected void onSaveInstanceState(Bundle state) {
     super.onSaveInstanceState(state);

     // Save list state
     mListState = mLayoutManager.onSaveInstanceState();
     state.putParcelable(LIST_STATE_KEY, mListState);
}

Restaurer l'état dans la onRestoreInstanceState():

protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);

    // Retrieve list state and list/item positions
    if(state != null)
        mListState = state.getParcelable(LIST_STATE_KEY);
}

Puis mettez à jour le LayoutManager (je le fais dans onResume()):

@Override
protected void onResume() {
    super.onResume();

    if (mListState != null) {
        mLayoutManager.onRestoreInstanceState(mListState);
    }
}
83
khusrav

J'ai trouvé une meilleure solution - Cette solution présente les avantages suivants:

  1. L’état de RecyclerView est enregistré et restauré sur rotation du téléphone
  2. L’état de RecyclerView est sauvegardé et restauré le retour à l’activité avec RecyclerView (qui n’a pas été détruit alors que l’autre activité était affichée - ce qui signifie que onRestoreInstanceState() n’appelle pas !!).

CODE

public class ActivityItemList extends AppCompatActivity
{
    private final String KEY_RECYCLER_STATE = "recycler_state";
    private RecyclerView mRecyclerView;
    private static Bundle mBundleRecyclerViewState;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);//set to whatever layout name you have

        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);//set to whatever view id you use
        // don't forget to set your adapter
    }

    @Override
    protected void onPause()
    {
        super.onPause();

        // save RecyclerView state
        mBundleRecyclerViewState = new Bundle();
        Parcelable listState = mRecyclerView.getLayoutManager().onSaveInstanceState();
        mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, listState);
    }

    @Override
    protected void onResume()
    {
        super.onResume();

        // restore RecyclerView state
        if (mBundleRecyclerViewState != null) {
            Parcelable listState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
            mRecyclerView.getLayoutManager().onRestoreInstanceState(listState);
        }
    }
}
20
Someone Somewhere

Utilisez ce code dans onPause() et onResume() pour enregistrer et restaurer la position de défilement.

private Parcelable recyclerViewState;
recyclerViewState = mrecyclerView.getLayoutManager().onSaveInstanceState();//save
mrecyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);//restore
10
mahandis mehdi

C'est ma solution, elle restaure les objets et la position de RecyclerView

1) enregistrer l'état d'affichage du recycleur dans la méthode onSaveInstanceState

@Override
protected void onSaveInstanceState(Bundle outState) {
    Parcelable listState = myRecyclerView.getLayoutManager().onSaveInstanceState();
    // putting recyclerview position
    outState.putParcelable(SAVED_RECYCLER_VIEW_STATUS_ID, listState);
    // putting recyclerview items
    outState.putParcelableArrayList(SAVED_RECYCLER_VIEW_DATASET_ID,mDataset);
    super.onSaveInstanceState(outState);
}

2) Vérifiez le paquet savedInstanceState dans la méthode onCreate

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState==null){
            getRemoteData(); // No saved data, get data from remote
        }else{
            restorePreviousState(); // Restore data found in the Bundle
        }
    }

3) Restaurer les données d'affichage du recycleur si l'écran a été pivoté

public void restorePreviousState(){
    // getting recyclerview position
    mListState = mSavedInstanceState.getParcelable(SAVED_RECYCLER_VIEW_STATUS_ID);
    // getting recyclerview items
    mDataset = mSavedInstanceState.getParcelableArrayList(SAVED_RECYCLER_VIEW_DATASET_ID);
    // Restoring adapter items
    mAdapter.setItems(mDataset);
    // Restoring recycler view position
    mRvMedia.getLayoutManager().onRestoreInstanceState(mListState);
}
7
Nicola Gallazzi
public class MainActivity extends AppCompatActivity {
Parcelable recyclerViewState;
.......
@Override
    protected void onPause() {
        super.onPause();
        recyclerViewState = MainAnecdotesView.getLayoutManager().onSaveInstanceState();//save
    }
    @Override
    protected void onResume()
    {
        super.onResume();
        if(recyclerViewState!=null)
            MainAnecdotesView.getLayoutManager().onRestoreInstanceState(recyclerViewState);//restore
    }
}
1
Vlad

Lorsque vous utilisez recyclerView.getLayoutManager().onSaveInstanceState(), n'oubliez pas de vérifier null:

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);

    if (recyclerView != null) {
        outState.putParcelable(SCROLL_POSITION, recyclerView.getLayoutManager().onSaveInstanceState());
    }
}
0
CoolMind