Skip to content Skip to sidebar Skip to footer

Fragment, Save Large List Of Data On Onsaveinstancestate (how To Prevent Transactiontoolargeexception)

In my app, I have Fragment which is inside ViewPager. Fragment contains RecyclerView with list of data fetched from web api based on user selection. On my Fragment onSaveInstanceSt

Solution 1:

To preserve big chunks of data, Google is suggesting to do it with Fragment that retain instance. Idea is to create empty Fragment without view with all necessary fields, that would otherwise been saved in Bundle. Add setRetainInstance(true); to Fragment's onCreate method. And than save data in Fragment on Activity's onDestroy and load them onCreate. Here is and example of Activity:

publicclassMyActivityextendsActivity {

private DataFragment dataFragment;

@OverridepublicvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // find the retained fragment on activity restartsFragmentManagerfm= getFragmentManager();
    dataFragment = (DataFragment) fm.findFragmentByTag("data");

    // create the fragment and data the first timeif (dataFragment == null) {
        // add the fragment
        dataFragment = newDataFragment();
        fm.beginTransaction().add(dataFragment, "data").commit();
        // load the data from the web
        dataFragment.setData(loadMyData());
    }

    // the data is available in dataFragment.getData()
    ...
}

@OverridepublicvoidonDestroy() {
    super.onDestroy();
    // store the data in the fragment
    dataFragment.setData(collectMyLoadedData());
}
}

And example of Fragment:

publicclassDataFragmentextendsFragment {

// data object we want to retainprivateMyDataObject data;

// this method is only called once for this fragment@OverridepublicvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // retain this fragmentsetRetainInstance(true);
}

publicvoidsetData(MyDataObject data) {
    this.data = data;
}

publicMyDataObjectgetData() {
    return data;
}
}

Solution 2:

If you don't want your fragment to use setRetainInstance(true), then you can add an empty fragment with setRetainInstance(true) to your activity. This is useful since child fragments cannot use setRetainInstance(true).

Example:

publicclassBaseActivityextendsActivity {

  RetainedFragment retainedFragment;

  @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    retainedFragment = (RetainedFragment) getFragmentManager().findFragmentByTag("retained_fragment");
    if (retainedFragment == null) {
      retainedFragment = newRetainedFragment();
      getFragmentManager().beginTransaction().add(retainedFragment, "retained_fragment").commit();
    }
  }

  public <T> T getState(String key) {
    //noinspection uncheckedreturn (T) retainedFragment.map.get(key);
  }

  publicvoidsaveState(String key, Object value) {
    retainedFragment.map.put(key, value);
  }

  publicbooleanhas(String key) {
    return retainedFragment.map.containsKey(key);
  }

  publicstaticclassRetainedFragmentextendsFragment {

    HashMap<String, Object> map = newHashMap<>();

    @OverridepublicvoidonCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setRetainInstance(true);
    }

  }

}

Then, in your fragment, you can cast getActivity() to your Activity class and use saveState(String, Object) and getState(String) to save your list.


There are other discussions on this which can be found at the following locations:

What to do on TransactionTooLargeException

android.os.TransactionTooLargeException on Nougat (Accepted answer suggests setRetainInstance(true)).

Solution 3:

setRetainInstance() is the best way to achieve that without side effects. Using static will cause memory leak and there is no use of saving the state in onSaveInstanceState() and getting it back since, setRetainInstance() does that for you.

So create a field for the list in fragment class and always check for null or size of list to begin operation of fetching latest data

Post a Comment for "Fragment, Save Large List Of Data On Onsaveinstancestate (how To Prevent Transactiontoolargeexception)"