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.
Related
I am new to developing on android, finding myself somewhat confused regarding fragments and activities, and when to use the former specifically.
I want to achieve the following:
Have an activity with buttons for displaying different graphs. The selected graph should appear on screen in a panel overlaying the screen, or in fullscreen, and it should have functionality/buttons e.g. for selecting a graph timeframe.
Would creating each graph-page as fragments, routing events to the main activity be a good idea here, or should I just make a new activity for each? Or are there better options?
Cheers
I wouldn't recommend to use separate activities for this task.
The fragments are a great option for your case. You can save the state of each fragment and thus avoid recreating the graph views every time (which saves lots of CPU time if amount of data is big).
Read info about FragmentTransaciton and of course learn about working with Fragments in general. Maybe you should also try using ViewPager if you want to avoid switching fragments by yourself.
In case of using ViewPager you should use FragmentPagerAdapter (this one saves fragments for you) and you will just switch between them from your MainActivity. In each of the fragments you will implement your own graph with its own (or shared) layout file.
This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible.
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.
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.
For couple of days, I have a question in my mind that couldn't find any answer for. Right now I have an android app that I use 1 fragment and a view pager with 3 fragments. What I wonder is, is there any performance difference between those two? Will using of fragments provide me less cost than using activities? What would be good for RAM/CPU of device while changing layouts; skip from one activity to another or skip between fragments of viewpager? Because if I use activity, than everytime a window will pop up. But in viewpager's fragment I will stay in one activity and will change only pages. Will that provide me performance on device or is just an UI issue?
Thanks in advance.
A ViewPager works in this way: Let's say it has n pages, or Fragments. If you are on index i, Android will ensure Fragments i-1 and i+1 and their Views are instantiated. As you page from side to side, subject to memory and the "Don't keep activities" setting, you will keep instantiating Fragments until all Fragments are present in memory. When you side from side to side, Android uses OpenGL to smoothly slide one Fragment's View over onto the screen while sliding the other out.
Contrary to some other answers, Android does not instantiate all Fragments when the ViewPager starts - instantiation is lazy. In addition to the default behaviour described above, you can control memory use using the setOffscreenPageLimit().
This is the key difference from the older Activity stack model which instantiates Activities only when called.
There are several consequences:
When the ViewPager is first shown, the CPU will be more active since it has to instantiate the Fragment being shown and those off-screen to the left and right (2x or 3x the equivalent work)
Since all the Fragments stay in memory, memory use will be (slightly) higher. If your Fragments don't use much memory, the difference in memory usage is trivial.
If there is memory pressure (or "Do not keep Activities" is on), then only 2 or 3 Fragments are kept; other fragments are suspended so you need to ensure the onSaveInstanceState() is implemented correctly. When the user slides back, the Fragments will be resumed. However, resuming a Fragment is less CPU intensive than creating the equivalent new Activity
Once the Fragments are instantiated, as the user slides from side to side, CPU use will be lower and (most importantly) the UX will be much smoother since the Views are already present and rendered in memory.
Communication between Fragments is relatively easy using the parent Activity as the communication hub.
One other point: The ViewPager's UI metaphor is different to the Activity stack. When weighing which approach to take, you probably should value the UX more than the implementation details (CPU and memory) unless the implementation costs are extreme.
There is the difference b/w those 2:
If you use fragments then the first time your activity load, it will load ALL of your fragments as once (a huge memory consumption here if you have many fragments, but in your case, 3 fragment maybe acceptable). But as it load ALL as once, you can move back and forward without delaying (it's obvious for a view pager anyway). So if the requirement allow users to move back and forward your pages then Fragment is the choice, the problem is how you can manage the memory consumption to avoid memory leak or out of memory exception.
If you use activity (many activities) instead of fragments then the memory will stack up every time you move forward and unstack every time you back. It seems more efficient but the problem many occurs if each activity contains a large image which take a bit long to load. Therefore, every time you move back or forward there WILL be a delay which is not nice for user to observe. So, if the requirement only allow user to move forward, the using activity instead of fragment is obviously right.
In conclusion, depending on your application requirements and how you manage the memory issue to use Fragment or Activity. These are only my experiences and observations, I'm not guarantee that's true in any cases. There maybe a better explanation that I haven't know yet. Hope this help and English is not my native language, if you don't understand leave comment below.
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