In the project I'm developing there's sequence of fragments that get swapped with replace: A -> B -> C.
One thing I don't like about it is that when the backstack is popped fragments get recreated and I lose UI settings and I also need to dance around data loading and the lifecycle. On the other hand if I were to use the add method it would not destroy the fragments but it also makes me worry about memory consumption - can it lead to OutOfMemoryException? Does the framework handle LRU hidden fragments?
Is there any way to combine benefits of add and replace? Maybe I should try to use add + hide?
Yes, add, hide, and show is what you want. Use add when you first create the fragments, hide the fragment you are replacing, and show a fragment that was previously showing. You don't want to use replace because that will tear down the view hierarchy of the old fragment, and you will lose the fragment's state.
Related
When using a fragment transaction we can do them using add and replace methods. If we use add, the previous fragment is not destroyed and kept in memory. And if we use replace the previous fragment is destroyed and recreated again when we go back. From an optimum (memory, cpu, etc) perspective what is more effective/better?
I've created a simple app that is capable of replace or add a fragment, you can find it here.
Following the android documentation I've used their tool to test the performace, those are the results:
By adding the fragment the usage of the cpu peaked was 17%
By replacing the fragment the usage of the cpu peaked was 23,3%
If you are talking about memory usage, then replace is better than add, because in add() the fragments's (which are in a stack of fragments) views are in memory, and all the images and views are taking memory, which is not released. Suppose you have 5 fragments A, B, C, D, E. You have added them one by one A->B->C->D->E Now E is at the top and all fragments A, B, C, D have their views and resources loaded in the memory, Suppose these fragments have a lot of heavy images, then there are chances your app may face out of memory. But If you use replace for each of them, their views are released so their resources are released (which is good, as these are no more visible to the screen, so should not hold resources, images and memory).
For more information, Google has introduced Jetpack navigation https://developer.android.com/guide/navigation
In this when fragments navigate from one to another, replace is performed.
The only thing required in case of replacing, is you need to handle onCreateView() properly so when the user comes back to destroyed fragment, Its views are populated again.
It depends on your scenario. Replace seems as better option generally because creating a new hierarchy doesn't cause a performance downfall and it releases its view hierarchy without destroying fragment instance if you save it to your back stack. However, there is some cases you should be aware of for example: you create a view like map view. It takes much time to create a view from scratch so you should keep that view in memory to prevent creating the view again and again user backs to this fragment. However if your memory starts to reach it bounds you should take care of it like destroying the fragment by using memory callbacks.
Most of the cases, replacing fragment is better option. You can see what happens when you add your fragment to a container without replacing previous one by not setting a background to your fragments.
As summary if your fragments take so much time to create its view hierarchy, you keep the view hierarch by transactions of show and hide not adding each fragment top of another. But if the fragment has a lightweight view hierarchy to create replace it.
As the title suggests, I want to retain my fragments. I have enforced my app orientation to always be in landscape mode in the manifest file so that there will be no rotations.
I have read:
Understanding Fragment's setRetainInstance(boolean)
and
Why use Fragment#setRetainInstance(boolean)?
However, I am not sure if they apply to my situation.
My project consists of a ViewPager with swipe tabs. How can I ensure that the fragments used in the ViewPager are the same ones as created when the MainActivity first starts? Would I use the same tagging method and findfragment by tag?
Additionally, where would it be best to check for the tagged fragment, else create a new fragment?
Just a side question related to ViewPager: what can I do to immediately create all fragments used in the ViewPager when the mainactivity is started, rather than to wait for a swipe event to occur?
To answer your last question view pager will by default create the fragments around the current fragment so you don't need to worry about that part. What I would recommend is let the view pager manage your fragments for you rather changing the behaviour since you might face performance issues.
SetRetainInstance simply keeps the instance of your fragment when its detached so it's up to you to assess whether you need to use it or not.. is there anything you want to maintain about that fragment? if not then do not use it, free your memory as much as possible.
For the last question, why do you want the same fragments created from the first time to be retained ? all the time? if you NEED to do that then rethink your structuring. gracefully recreate your fragments and maybe have some caching of your data on another layer if that is what you are worried about.
CONSTRUCTION
I've got Activity that holds a "path" made of Fragments.
The User goes from Fragment1 to Fragment2 and then to Fragment3 filling up the required informations. Nothing fancy here just plain backStack and .replace made on Fragments.
QUESTION
How should I retain that information when orientation changes to get my backStack back the way it was before orientation change?
IDEAS
The only idea I have is to insert into saveInstanceState the last visible Fragment and recreate things from there but it feels really hacky and I think in the long run it's going to make some major problems.
/////////////UPDATE//////////////
It looks like nowadays Android is capable of doing it on its own as long as you are following the guidelines provided by ARTICLE
The backstack itself is saved and loaded automatically with the activity.
Here's an article how Android does save and load activity and fragment states.
What you should care of is implementing the same logic of saving and restoring states for each fragment.
After spending a fair bit of time figuring out that the reason my fragments chosen from a drawer layout weren`t displaying sometimes due to the choreographer skipping frames (I was using transaction.replace rather than show/hide) it made me wonder -- what are the situations where one would want to use replace rather than show/hide or detach/reattach? My problem went away when I switched to using show/hide btw.
Taken from this thread I got this on what happens when you call FragmentTransaction.replace():
Android will effectively perform a sequence of
FragmentTransaction.remove(...) (for all Fragments currently added to
that container) and FragmentTransaction.add(...) (for your supplied
Fragment). Removing a Fragment from the FragmentManager will cause the
Fragment to be destroyed and its state will no longer be managed. Most
noticeably, when you re-add the Fragment all of the views will have
been reset. Note: since you are reusing the same Fragment instance,
the Fragment will still keep the value any instance variables.
and from this thread I got that it is probably better to show/hide rather than replace if you plan on using that fragment again. My question is, in which situations do you use FragmentTransaction.Replace()? The only place I could see it really being useful is for something you know you won`t need again, kind of like a dialog picker with options but I use dialog fragments for those situations.
Does anyone use FragmentTransaction.replace regularly, and if so, why did you choose that over another method? Cheers
It maybe useful, for example, when implementing a deep fragments hierarchy in Multi-pane pattern (when click on item in the right fragment moves it to the position of the left).
Also, since hiding a Fragment keeps it in FragmentManager, it maybe expensive if you have a heavy content in it or hide multiple instances. Calling remove() or replace() and properly saving fragment's state is more Android-way, I think.
can anybody tell how is fragment advantage over using instead of view in android
Thanks
Advantage is that Fragment has a lifecycle which is tied to the lifecycle of the Activity and you can control behavior much more easily.
Also Fragments can be put on backstack using FragmentTransactions which is not possible using views
Fragments are considered as sub activities to be used in one specific activities these fragment are often will reduce activity switching and reduces complexity and If view are added then these cannot have stack management
if activity viewed a view and cannot go back to previous view unless we code but in fragment has similar life cycle method it would maintain other information about previous view
Since Activitymanager even maintain the activity stack for previous menu. its similar to fragment