28

I'm referring to Why use Fragment#setRetainInstance(boolean)?

The reason I ask so is for Activity to handle rotation, Official Activity Documentation encourages us to let Activity shut-down and restart during rotation.

android:configChanges Lists configuration changes that the activity will handle itself. When a configuration change occurs at runtime, the activity is shut down and restarted by default, but declaring a configuration with this attribute will prevent the activity from being restarted. Instead, the activity remains running and its onConfigurationChanged() method is called. Note: Using this attribute should be avoided and used only as a last-resort. Please read Handling Runtime Changes for more information about how to properly handle a restart due to a configuration change.

Any attempt to change this Activity default behavior seems to be bad practice. To avoid Activity from reloading time consuming data structure during restarting, we make make use of onRetainNonConfigurationInstance and getLastNonConfigurationInstance. - Official Handling Runtime Changes

However, when comes to handling rotation in Fragment, does Google give us different recommendation? They do not want us to shut down and restart Fragment?

public Object onRetainNonConfigurationInstance ()

This method was deprecated in API level 13. Use the new Fragment API setRetainInstance(boolean) instead; this is also available on older platforms through the Android compatibility package.

  1. Why does Google encourage us to shut down and restart Activity during rotation, but encourage us to retain Fragment during rotation?
  2. If setRetainInstance(true) is good in handling rotation, why don't Google make it as Fragment's default behavior?
Community
  • 1
  • 1
Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875

2 Answers2

33
  • Configuration changes: when suddenly screen becomes much wider and much less in height (typical landscape), it is apt for a visual component to update its display and more intelligently use the screen available. Another examples of config change are user sliding the hardware keyboard, device language changing, and so on. why re-start :

    • Android components favor declarative layout, you load a bunch of XML layouts, and work from there. Finding every View and re-arranging/updating it in real time will be a mess, not to mention the re-wiring of all the event handlers and other custom View code. Its way easier to reload another bunch of layout files.

    • Also, In Android, Activities kind of live at the mercy of system, so naturally, Activity life cycle is so designed (and recommended) that it is capable of re-creating itself on demand , any time, just as it was before it was destroyed. This pattern accommodates all re-starts, those due to configuration changes as well. If you make your Activities and Fragments capable of maintaining an eternal state, configuration changes won't be that much of a problem.

    • Retain state data (Models), not the stuff displaying it (UI and Views).

  • setRetainInstance(true): It is recommended only to be used with fragments that do not hold any reference to anything, that will be recreated on rotation. This means you should not use it on any Fragment that holds Context, Views, etc. A typical Visual fragment does. But it is very useful with Fragments that hold objects like running Threads, AsyncTasks, Data Collections, loaded assets, fetched results etc. This method helps in using a non visual Fragment, as a detachable holder, for non Context-dependent objects of an Activity.

S.D.
  • 29,290
  • 3
  • 79
  • 130
  • Yes forgot why it wasn't smart to use with Views but Context leak is the answer. – Warpzit Feb 25 '13 at 12:03
  • 3
    **"It is only to be used with fragments that do not hold any reference to anything that will be recreated on rotation."** I'm not so sure that this is 100% accurate. If the retained fragment sets a reference to the parent `Activity` in `onActivityCreated(Bundle)` (which will be called in the retained fragment after each configuration change), then shouldn't this be enough to ensure that the retained `Fragment` never holds a reference to an old `Activity`? – Alex Lockwood Apr 22 '13 at 00:10
  • 4
    @AlexLockwood If you look at source code,`FragmentManager` sets the `mActivity` field of a fragment to its parent activity on attach, and also **sets it back to null**, when that fragment is detached. In the fragment that field is accessible by `getActivity()`. So storing another reference to parent activity is not always required, and if one does so, one must clear/release it on detach. True, if you are careful enough to make sure you won't leak context references, you can use it in any way. My intent was to discourage senseless use of `setReatainInstance()` on just any Fragment. – S.D. Apr 22 '13 at 04:52
  • @user117 Gotcha. I just would have used different wording that "it is **only** to be used with...", that's all. I agree though that it probably doesn't make sense to hold a reference to the parent Activity manually... not sure why I recommended that in my comment. Like you said, `getActivity()` will work since it is set in `onAttach()` and set to `null` in `onDetach()`. :) – Alex Lockwood Apr 23 '13 at 04:57
  • Sorry to belabor the point, but why do you say 'A typical Visual fragment does.' Don't ALL fragments that display views hold views? The reason I ask is I have a fragment that inflates a view in onCreateView(), then returns the view. I don't keep a reference to the view, as in I don't save it as a fragment's attribute. Do these views have a reference to the old activity, or are their references updated? – flobacca Mar 18 '16 at 09:56
4

Because you are misunderstanding its use. setRetainInstance(true) should only be used in fragments that are like solo elements/modules. Fragment that handle sockets etc. an don't have a GUI really benefit from being retained. Fragments with a GUI should probably not use setRetainInstance(true). Also any fragments that goes to the backstack shouldn't use setRetainIstance(true).

You could generalize it to any fragment which handles only data/connection etc. should use setRetainInstance(true). But there is a multitude of different ways to use Fragments, which wouldn't benefit of setRetainInstance(true).

Warpzit
  • 27,966
  • 19
  • 103
  • 155
  • 1
    Any sources which supports your idea? Google Android documentation doesn't specific exactly on UI and non UI fragment. – Cheok Yan Cheng Feb 25 '13 at 11:58
  • If you look at googles reference on setRetainInstance(true) it at least doesn't work with backstack. Link: http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean) – Warpzit Feb 25 '13 at 12:01