I've read that setting .setOnRetainInstance(true)
on fragments presenting UI may lead to memory leaks.
Could somebody please explain why and how this would happen? I didn't find a detailed explanation anywhere.
I've read that setting .setOnRetainInstance(true)
on fragments presenting UI may lead to memory leaks.
Could somebody please explain why and how this would happen? I didn't find a detailed explanation anywhere.
Be careful when retaining certain objects that are coupled to the Activity.
Caution: While you can return any object, you should never pass an object that is tied to the Activity, such as a Drawable, an Adapter, a View or any other object that's associated with a Context. If you do, it will leak all the views and resources of the original activity instance. (Leaking resources means that your application maintains a hold on them and they cannot be garbage-collected, so lots of memory can be lost.)
http://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject
you can overide
onDestroy()
and invoke garbage collector.In a
Fragment
with UI you often save someView
s as instance state to speed up access. For example a link to yourEditText
so you don't have tofindViewById
it all the time.The problem is that a
View
keeps a reference to theActivity
context. Now if you retain aView
you also retain a reference to that context.That is no problem if the context is still valid but the typical retain case is restarting the Activity. Very often for a screen rotation for example. Activity recreation will create a new context and old contexts are intended to be garbage collected. But it can't be garbage collected now since your
Fragment
still has a reference to the old one.Following example shows how not to do it
To get rid of that problem, you need to clear all references to your UI in
onDestroyView
. Once theFragment
instance is re-used you will be asked to create a new UI ononCreateView
. There is also no point in keeping the UI afteronDestroyView
. The Ui is not going to be used.The fix in this example is just changing
onDestroyView
toAnd besides keeping references to
View
s you should obviously not keep references to theActivity
(e.g. fromonAttach
- clean ononDetach
) or anyContext
(unless it's theApplication
context).setRetainInstance(true)
is used to retain instances of dynamic Fragments during an Activity recreation, such as a screen rotation or other config changes. This does not mean the Fragment will be retained forever by the system though.When an Activity is terminated for other reasons, such as the user finishing the Activity (i.e. pressing back), the Fragment should be eligible for garbage collection.
The "setRetainInstance" is used to maintain the state of the fragment when the activity is recreated. According to the official documentation: if we use "setRetainInstance", 2 methods of the fragment's lifecycle will not be executed (onCreate, onDestroy). However, the views contained in the fragment will be recreated, and that is because the lifecycle will be executed from the "onCreateView". In these cases, if we have saved some data in "onSaveInstanceState", we should ask for it in the "onActivityCreated" instead of in the "onCreate".
Oficial info: https://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
More info: https://inthecheesefactory.com/blog/fragment-state-saving-best-practices/en