72

I find Fragment#setRetainInstance(true) confusing. Here is the Javadoc, extracted from the Android Developer API:

public void setRetainInstance (boolean retain)

Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. If set, the fragment lifecycle will be slightly different when an activity is recreated:

  • onDestroy() will not be called (but onDetach() still will be, because the fragment is being detached from its current activity).
  • onCreate(Bundle) will not be called since the fragment is not being re-created.
  • onAttach(Activity) and onActivityCreated(Bundle) will still be called.

Question: How do you as a developer use this, and why does it make things easier?

Håvard Geithus
  • 5,544
  • 7
  • 36
  • 51

4 Answers4

93

How do you as a developer use this

Call setRetainInstance(true). I typically do that in onCreateView() or onActivityCreated(), where I use it.

and why does it make things easier?

It tends to be simpler than onRetainNonConfigurationInstance() for handling the retention of data across configuration changes (e.g., rotating the device from portrait to landscape). Non-retained fragments are destroyed and recreated on the configuration change; retained fragments are not. Hence, any data held by those retained fragments is available to the post-configuration-change activity.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • @CommonsWare - If you create a new fragment in an Activity and that Activity is recreated, how do avoid creating a new fragment again? – Neil Oct 19 '12 at 20:26
  • 4
    @Neil: See if the fragment exists (e.g., `findFragmentById()`). Don't recreate it if it exists. – CommonsWare Oct 19 '12 at 22:44
  • @CommonsWare If the fragment is a bit heavy with views and memory usage, what do you think a good developer should do? – android developer Apr 21 '13 at 09:51
  • @androiddeveloper: Views aren't an issue, so long as the fragment is not directly holding onto them, as they are always discarded and recreated. I'm not quite certain how a fragment itself would be "heavy" in terms of "memory usage" -- do you have an example? – CommonsWare Apr 21 '13 at 11:27
  • @CommonsWare If the fragment holds its views so that it won't have to re-create them (in the onCreate() method), it might take some memory. However, I think it's ok to use softReference/weakReference for this task instead, right? – android developer Apr 21 '13 at 11:52
  • 1
    @androiddeveloper: "If the fragment holds its views so that it won't have to re-create them (in the onCreate() method), it might take some memory" -- you are welcome to attempt to re-parent the widgets into the new activity, but I have had zero luck with that. AFAIK, you need to recreate the widgets in `onCreateView()`. "However, I think it's ok to use softReference/weakReference for this task instead, right?" -- what task? – CommonsWare Apr 21 '13 at 12:04
  • @CommonsWare It is possible. You check the parent of the view that was stored before (check for null of course) and if there is a parent, you remove the fragment from its parent. Of course, it might not work well on some cases so you always have to put the fragments in a single layout and never put other views in the layout. About the "task" I meant the fact of avoiding re-creation of views without any problems. – android developer Apr 21 '13 at 14:18
  • @CommonsWare Is it possible to make a call setRetainInstance(true) in onCreate()? – e.shishkin May 03 '13 at 16:55
  • 3
    @e.shishkin: It should be. I rarely implement `onCreate()` in a fragment, so I have not tried it. – CommonsWare May 03 '13 at 17:00
  • 1
    @e.shishkin You can call it anytime you want. Technically you don't even need to call it in the lifecycle methods (although this is generally not something you would ever want/need to do). – Alex Lockwood Aug 21 '13 at 16:56
  • will this apply to a ListFragment if a user needs to dive into a hierarchy, then "getRetainInstance()" if the user hits the back button? Or is the general practice to use "addToBackStack" to recreate a past ListFragment if it's a two pane app? – whyoz Mar 20 '14 at 19:07
  • @whyoz: Sorry, but I have no idea what you are talking about. – CommonsWare Mar 20 '14 at 19:10
  • ListFragment 1 (click listView row, commit transaction) >>> ListFragment 2 >>> (click) BACK BUTTON >>> retrieve/restore ListFragment 1 without reloading data – whyoz Mar 20 '14 at 19:46
  • @CommonsWare will it helpful in re-opening app from recent apps list and retain the state of fragment? – Raghavendra Oct 14 '15 at 11:41
  • @Raghavendra: Only if the process was still around. – CommonsWare Oct 14 '15 at 12:06
  • @CommonsWare thanks for your reply. Can you give me solution for my problem. I have a Fragment which contains a listview when I hit home button and suppose if GC is initiated I lost my data which is listview when I try to open the app again its crashing. can you help me in this – Raghavendra Oct 14 '15 at 12:09
49

It's very helpful in keeping long running resources open such as sockets. Have a UI-less fragment that holds references to bluetooth sockets and you won't have to worry about reconnecting them when the user flips the phone.

It's also handy in keeping references to resources that take a long time to load like bitmaps or server data. Load it once, keep it in a retained fragment, and when the activity is reloaded it's still there and you don't have to rebuild it.

DeeV
  • 35,865
  • 9
  • 108
  • 95
  • Nice. But what if we need to refresh them? – Anshul Tyagi Mar 04 '16 at 10:25
  • Am I wrong in thinking that this is what a Singleton of some sort would normally do? – rupinderjeet Jun 09 '21 at 12:05
  • @rupinderjeet yes. A Singleton is another way of doing it. Singletons are considered "anti-patterns" and some people are hesitant to use them. Fragments also have the advantage of being tied to the lifecycle of the activity so you get lifecycle events. You can destroy the resource if the user leaves the app for example (which can also be done with Singleton but takes more code). – DeeV Jun 10 '21 at 11:17
35

Added this answer very late, but I thought it would make things clearer. Say after me. When setRetainInstance is:

FALSE

  • Fragment gets re-created on config change. NEW INSTANCE is created.
  • ALL lifecycle methods are called on config change, including onCreate() and onDestroy().

TRUE

  • Fragment does not get re-created on config change. SAME INSTANCE is used.
  • All lifecycle methods are called on config change, APART FROM onCreate() and onDestroy().
  • Retaining an instance will not work when added to the backstack.

Don't forget that the above applies to DialogFragments as well as Fragments.

Ryan M
  • 18,333
  • 31
  • 67
  • 74
Eurig Jones
  • 8,226
  • 7
  • 52
  • 74
5

The setRetainInstance(boolean) method is deprecated, use ViewModels instead.

The setRetainInstance(boolean) method on Fragments has been deprecated as of Version 1.3.0 of fragment API.

With the introduction of ViewModels, developers have a specific API for retaining state that can be associated with Activities, Fragments, and Navigation graphs. This allows developers to use a normal, not retained Fragment and keep the specific state they want retained separate.

This ensures that developers have a much more understandable lifecycle for those Fragments (one that matches all of the rest of their Fragments) while maintaining the useful properties of a single creation and single destruction (in this case, the constructor of the ViewModel and the onCleared() callback from the ViewModel).

Darish
  • 11,032
  • 5
  • 50
  • 70