Using `onRetainCustomNonConfigurationInstance` to retain data across configuration changes

wasyl picture wasyl · Jun 5, 2015 · Viewed 7.2k times · Source

I've been programming for Android for some time, and I'm still looking for solutions to retain data over configuration changes. Aside from saving Parcelables to Activity's Bundle in onSaveInstanceState docs are suggesting using Fragment with setRetainInstance flag set to true.

But I've just come across some code that uses onRetainCustomNonConfigurationInstance to hold arbitrary objects (in a fancy way, but essentially big objects without references to Activity etc.). I have never seen this method used, so I have some doubts:

  • Is this method safe to call to store arbitrary objects (in a sense that I can be pretty sure it's gonna get called, and that it won't be deprecated/removed anytime soon)?
  • How is this method different from onRetainNonConfigurationInstance(), which also should return Object, and in essence should work similarly?
  • Is using retained fragment still better, for some reason?

As a bonus, I would be grateful for any other tips or solutions to save state of objects like AsyncTask, Observable, view's presenters and go on

Answer

sergej shafarenka picture sergej shafarenka · Jun 25, 2015

Is this method safe to call to store arbitrary objects (in a sense that I can be pretty sure it's gonna get called, and that it won't be deprecated/removed anytime soon)?

onRetainCustomNonConfigurationInstance() is a relatively new method and it is not deprecated. I would really assume it is not going to disappear soon, because there is no reason for introducing something new just to remove it. You can use it safely.

How is this method different from onRetainNonConfigurationInstance(), which also should return Object, and in essence should work similarly?

onRetainNonConfigurationInstance() always return an instance of inner NonConfigurationInstances class with retained fragments, loaders etc states. You cannot (and should not) change this system behavior. That's why the method is final and you cannot override it.

If you want to retain your custom instance, you need to override onRetainCustomNonConfigurationInstance() and return it from there.

In fact, onRetainNonConfigurationInstance() calls onRetainCustomNonConfigurationInstance() and retains retuned instance with the other states like retained fragments and loaders.

Is using retained fragment still better, for some reason?

It is rather a matter of your use case and preferences. The logic might be like this. If your activity just controls fragments and has no other special logic in it, then it is easier to use retained fragments. If your activity has something to retain, then you can safely use onRetainCustomNonConfigurationInstance() method. As for now, in both cases the state still gets retained by good old and deprecated onRetainNonConfigurationInstance() method.

p.s. Regarding the bonus question about storing a state I would rather suggest to look at onSaveInstanceState() method. It was intended for storing states.

Update: AndroidX release from November 5, 2018 deprecated the method with the following note: onRetainCustomNonConfigurationInstance has been deprecated. Use a ViewModel for storing objects that need to survive configuration changes.