androidandroid-fragmentsandroid-recyclerviewsavestateonsaveinstancestate

How to store recyclerview data , while changing view (Fragments) via Bottom Navigation?


I am following this question

how to store recyclerview data on onSaveInstanceState

I also found How to save state of view class? and Fragment save view state.

Context

I give data in form of DataModel (implements Parcelable) to recyclerview in one of my Fragments. using Bottom navifation and ROOM DB (to get and save Data).

what I have done yet

I used the code in first link and in my code. But I couldn't understand the fourth peace of code, which was used in there (I don't have a response.boddy(), Error). Anyway every time changing the view savedInstanceState = null so the code is being redone.

what I want or question

I would like to not redo the work every time changing the view via bottom navigation?

what am I doing wrong, that data are not being saved in savedInstanceState?

my Fragment view

    private ArrayList<DataModel> data;

    public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {
    
    root = inflater.inflate(R.layout.fragment_home, container, false);
    currentContext = getContext();
    
    
    recyclerView = (RecyclerView) root.findViewById(R.id.recyclerViewHome);
    recyclerView.setHasFixedSize(true);


    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    this.data = new ArrayList<>();
    
    adapter = new CustomAdapter(data, currentContext, 1);
    recyclerView.setAdapter(adapter);

    
    if (savedInstanceState != null) {
        
        // Retrieve the data you saved
        data = savedInstanceState.getParcelableArrayList("saved_data");

        //Call method to reload adapter record
        recyclerViewsaveInstance(data);
    } 
     else {
        
        //No data to retrieve

        dataAsynTask; //deleted, Basicly I get the data from DB, convert it to DataModel and give them to recyclerview.
    }

    return root;
}

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

    Log.i("savedInstanceState", "loading");
    
    savedInstanceState.putParcelableArrayList("saved_data", this.data);
    
    super.onSaveInstanceState(savedInstanceState);

}


public void recyclerViewsaveInstance(ArrayList<DataModel> dataset)
{
    this.data = dataset;
    adapter = new CustomAdapter(dataset, getContext(), 1);
    recyclerView.setAdapter(adapter);//notify adapter about the new record
    adapter.notifyDataSetChanged();
}

Solution

  • I think what you want to do here is to move your AsyncTask out to the Activity level, and have your Fragment ask the Activity for the List<DataModel>.

    In your Fragment's onCreateView() method, instead of writing

    this.data = new ArrayList<>();
    

    and then checking savedInstanceState and conditionally executing an AsyncTask, you could write this:

    this.data = ((MyActivity) getActivity()).getData();
    

    Then, in your Activity, you'd implement this getData() method:

    public List<DataModel> getData() {
        if (data != null) {
            return data;
        } else {
            // kick off AsyncTask here
            return Collections.emptyList();
        }
    }
    

    When the AsyncTask finishes, have it update the Activity's data field and also have it notify the Fragment that new data is available. In the Fragment, you'd have a method like this:

    public void onDataFetched(List<DataModel> data) {
        this.data = data;
        adapter.notifyDataSetChanged();
    }
    

    The end result of all of the above is that the Activity is now responsible for loading the data and for saving it. The Fragment doesn't know anything about the database or caching; it just knows to ask the Activity for the data whenever it is shown.

    Since the Activity stays alive while you switch between Fragments with your bottom nav, it will successfully keep the data alive when you switch tabs.