4

I have an activity with a ViewPager and 3 fragments called A,B,C. A has a recyclerView populated by cardView and each card implements and OnClickListener which leads to a new Activity D. I want to be able to save the recyclerView scroll position when switching in tabs and when coming back from the opened activity D.

what i did so far in Fragment A (the one containing the RecyclerView looks like this :

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    recyclerView = (RecyclerView)inflater.inflate(R.layout.event_fragment_layout, container,false);

    linearLayoutManager = new LinearLayoutManager((getActivity()));
    recyclerView.setLayoutManager(linearLayoutManager);
    recyclerView.setHasFixedSize(true);

    return recyclerView;

}

public void onStart(){
//This is where my adapter is created and attached to the recyclerView
recyclerView.setAdapter(myadapter)

 }

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

    outState.putParcelable(RECYCLER_STATE,linearLayoutManager.onSaveInstanceState());
    String saved = linearLayoutManager.onSaveInstanceState().toString();
    Toast.makeText(getContext(),"Saving Instance State",Toast.LENGTH_SHORT).show();
    Log.d("SAVE_CHECK ", saved);
}


@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {

    if(savedInstanceState!=null) {

        Parcelable savedRecyclerViewState = savedInstanceState.getParcelable(RECYCLER_STATE);
        if(savedRecyclerViewState!=null) {
            linearLayoutManager.onRestoreInstanceState(savedRecyclerViewState);
            Toast.makeText(getContext(), "Restoring Instance State", Toast.LENGTH_SHORT).show();
        }
        else{
            Toast.makeText(getContext(), "SAVED STATE IS NULL", Toast.LENGTH_SHORT).show();

        }

    }
    super.onViewStateRestored(savedInstanceState);
}

I'm displaying both the Toast, so the block is executing (and that means the savedRecyclerViewState is not null) but the recyclerView always starts from the first Card no matter what. Also when i open a new Activity by clicking on a card and then come back to Fragment A i get the Toast notificaton that the state is being saved but not the one in onViewRestored. What is basically happening from my understanding is that my linearLayoutManager's state gets saved but then i'm somehow failing to pass the info to restore the scrolling position. What am i doing wrong ?

SOLVED: solved it by myself but this might help some one it the future. TL;DR -> just declare the adapter in the onCreateView and then call yourRecyclerView.setAdapter(yourAdapter) both in OnCreateView and OnResume(),rest of the code remains the same

What happened then ? Simply enough i was correctly saving the linearLayoutManager state in onSavedInstanceState() and then correctly restoring it in OnCreate but i was unable to notice any difference it since the saved state state was being "overwritten" by setting my adapter in the OnStart. In steps :
1)fragment activity calls onSavedInstanceState and saves the LinearLayoutManager of my RecyclerViewin a Parcelable.
2)the app goes back to the fragment and calls onViewStateRestored()/OnCreateView(),there we read from the parcelable and restore our recyclerViewState
3)Now the problem OnStart() gets called and of course this is where my adapter is declared and then set to the recyclerView. Now the old recyclerView(the one with the saved state) is gone and is replaced by a fresh new recyclerView with no record of the previous one.

So just by simply setting the adapter in the OnResume() method you'll solve the problem. I guess you could also solve it by leaving the code in OnStart(), store the old recyclerView state and then passing it to the new recyclerView at the end of OnStart() but it's not a really clean solution

Davide Valiante
  • 155
  • 2
  • 12

0 Answers0