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

Je migre mes ListViews vers RecyclerViews. Avec les listes de lecture, j’ai utilisé la technique commune décrite ici pour stocker et restaurer la position de défilement entre les activités.

Comment faire de même avec RecyclerViews? le RecyclerView.onSaveInstanceState() semble avoir protected access protected , il ne peut donc pas être utilisé directement.

Ok, donc pour répondre à ma propre question. Si je comprends bien, comme ils ont découplé le code de mise en page et le code de recyclage des vues (donc le nom), le composant responsable de l’état de la mise en page (et de sa restauration) est désormais le LayoutManager utilisé dans votre recyclerview.

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

 protected void onSaveInstanceState(Bundle state) { super.onSaveInstanceState(state); // Save list state mListState = mLayoutManager.onSaveInstanceState(); state.putParcelable(LIST_STATE_KEY, mListState); } 

Etat de restauration dans le onRestoreInstanceState() :

 protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); // Resortingeve list state and list/item positions if(state != null) mListState = state.getParcelable(LIST_STATE_KEY); } 

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

 @Override protected void onResume() { super.onResume(); if (mListState != null) { mLayoutManager.onRestoreInstanceState(mListState); } } 

J’ai trouvé une meilleure solution – cette solution présente les avantages suivants:

  1. L’état RecyclerView est enregistré et restauré lors de la rotation du téléphone
  2. L’état RecyclerView est enregistré et restauré à son retour à l’activité avec RecyclerView (qui n’a pas été détruit pendant que l’autre activité était onRestoreInstanceState() – ce qui signifie que onRestoreInstanceState() n’est pas appelé !!)

CODE

 public class ActivityItemList extends AppCompatActivity { private final Ssortingng 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); } } } 

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 

C’est ma solution, il restaure les éléments et la position 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 bundle 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 de vue 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); } 

Lorsque vous utilisez recyclerView.getLayoutManager().onSaveInstanceState() n’oubliez pas de vérifier la valeur null :

 @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); if (recyclerView != null) { outState.putParcelable(SCROLL_POSITION, recyclerView.getLayoutManager().onSaveInstanceState()); } } 
 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 } } 

Étant donné que vous avez défini RecyclerView ( mRecyclerView ) et LayoutManager ( mLayoutManager ) dans votre code et que tout fonctionne mPosition , la solution pour enregistrer la position ( mPosition ) de votre RecyclerView ressemble à ceci:

  1. Variables et constantes utilisées:

     private final Ssortingng RECYCLER_POSITION_KEY = "recycler_position"; private int mPosition = RecyclerView.NO_POSITION; private RecyclerView mRecyclerView; private LinearLayoutManager mLayoutManager; private static Bundle mBundleState; 
  2. Dans la méthode onPause :

     @Override protected void onPause() { super.onPause(); // Save RecyclerView state mBundleState = new Bundle(); mPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition(); mBundleState.putInt(RECYCLER_POSITION_KEY, mPosition); } 
  3. Dans la méthode onResume :

     @Override protected void onResume() { super.onResume(); // Restore RecyclerView state if (mBundleState != null) { mPosition = mBundleState.getInt(RECYCLER_POSITION_KEY); if (mPosition == RecyclerView.NO_POSITION) mPosition = 0; // Scroll the RecyclerView to mPosition mRecyclerView.smoothScrollToPosition(mPosition); } } 
  4. Dans la méthode onSaveInstanceState :

     @Override public void onSaveInstanceState(Bundle outState) { // Save RecyclerView state outState.putInt(RECYCLER_POSITION_KEY, mLayoutManager.findFirstCompletelyVisibleItemPosition()); super.onSaveInstanceState(outState); } 
  5. Dans la méthode onRestoreInstanceState :

     @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { // Restore RecyclerView state if (savedInstanceState.containsKey(RECYCLER_POSITION_KEY)) { mPosition = savedInstanceState.getInt(RECYCLER_POSITION_KEY); if (mPosition == RecyclerView.NO_POSITION) mPosition = 0; // Scroll the RecyclerView to mPosition mRecyclerView.smoothScrollToPosition(mPosition); } super.onRestoreInstanceState(savedInstanceState); }