How much Fragmentation can be optimized before breaking the application - android

Recently on the app I have started working, I thought to go full OOP and try out Fragments to make the UI most flexible and reusable as possible.
At least that was the plan.
Here is where I encountered some issues.
I have a BottomNavigationView in my app that has four tabs. Therefore, 4 different fragments.
HomeFragment
InboxFragment
FavoritesFragment
ProfileFragment
I believe, if I'm using bottomNavigationView, this much fragmentation is unavoidable.
Then when I started to fill out the HomeFragment with content, I find that the file is getting too complicated and huge to easily examine specific parts. This is where I get the idea to create fragments of features that may get used in other activities/views.
So, one such individual fragment is AdvertisementFragment.
Here's where things get interesting. AdvertisementFragment uses code that employs Timer.schedule/Thread.sleep; something to delay a certain function called update.
But the code wasn't being delayed, it sped up instead. Checking the Logcat showed messages like
Frame time is 8.006377 ms in the future! Check that graphics HAL is generating vsync timestamps using the correct timebase.
OR
Skipped 2 frames! The application may be doing too much work on its main thread.
I only create the dummy apps for my employer, i.e. If you will, say a "working" demo. I'm just a UI designer for them.
Now when I saw these messages popup in my logcat, my first thought was to experiment, how much my device can take before the app crashes. I frantically click away on the four tabs of my bottomNavigationView and sure enough I see the first problem.
Nothing is being loaded in the fragments, its just a white background. All the components, Fragment or Not, weren't showing up, in any of the fragments. Then after a few more seconds it crashed. I test the same on two physical devices, and sure enough, it was not the emulator that crashed, my code was the problem.
Even though, it is not my job for optimizing the code, it is going to be a real pain for the developers/users of the app, for the mess that will emerge out of my faulty working model. Hell, if the developers had to redo that, it's going to be more costly.
Which is why, I'm here, is using Fragments within Fragments a good idea? I know about saving Fragment states, but can severely Fragmented code be a nuisance to the memory and optimization? If you are talking about saving states of every fragment then would it not consume more memory?
Say, I have a HomeFragment, InboxFragment, etc, from above, which I load into MainActivity. I can switch between these parent fragments with a bottomNavigationView. Say, HomeFragment itself has 3-5 fragments and rest of the code in HomeFragments is specific to HomeFragment. In other words, let's assume that 40% of code in HomeFragment is Fragments, and the 60% is code specific to HomeFragment. How does that impact performance? What if other parent fragments (InboxFragment, ProfileFragment, etc) have similar constitution of Fragments and Activity specific code?
Can this much Fragmentation be easily/somehow optimized? Or is it outright bad practice?

Related

Quick question: Can too many fragments make an app slow and how many?

I can't seem to find an answer for that. How many fragments can an app have, or how many xml layouts in general, before it starts getting cluttered and slow? All I found was that with too many nested layouts the activity itself performs worse.
Yes, theoretically it can. But it's not the number of fragments which can make an app slow, it's the way you use them. Even 2 fragments, if badly used, can make an app slow. On the other hand, tens of fragments could be handled fine. If your app instead needs 50, or 100 fragments, unless it's a really complex app and you're on top of it, then it's a good indicator that you're doing something wrong, either in the app flow, or the design. Android Studio provides you very good tools for profiling an app, use them, see where your bottlenecks are, and fix them. Measure the improvements before and after the fix.
No, there is no limit on making any number of fragments in Android app. And it does not harm any app if you make hundreds of fragments. But the way you are using those it DOES MATTER. As far as the matter of nested layout is concerned, yes it all depends upon your hierarchical level. Suitable approach should be used. Obviously not all layouts you will be showing in your activity. On depends or in certain conditions you will be using different nested layout. If this is the case then you can use fragment for dynamically update the UI or the Activity or Secondly you can dynamically add the views in your activity on demand. All at once if you are going to show complex nested layouts and those are in deep as well, this can cause sometimes some jerk or flick to load.To overcome this, You need to first think about weather it is necessary to load all the views else load on demand. Hope that helps you.

Differences between FrangmentTransaction and Intent

As taught by Udacity, typically one should use an intent to start a new activity (which presumably shows new/different information). But, for the project I'm currently working on I've been using FragmentTransaction to show different areas of the app. I figure this would lead to a smaller apk (b/c no java/xml files for different activities), but are there any benefits that I'm not taking into account (that would indicate that I should be using intents over FragmentTransactions)?
In my opinion it is up to you what you are using. Intents and FragmentTransaction have both their benefits and are useful in some situations more and in other less. I think it often depends on what you want to do with FragmentTransactions. One big benefit of Intents are the Extra Bundles with which you can share data directly, in FragmentTransaction the communication between the data is more complicated. I think you should try out both for yourself and than decide which is in certain situations useful.
The APK size difference would be insignificant. XML and class files are compressed when archived into an APK. They are relatively small anyway.
Fragments were created to provide a way to share screen UI components between different screen / device form factors.
E.g., imagine a point of sale app with a section that shows the order line items, a section that shows the inventory that can be added to the order, and a section that shows the total dollar amounts for the order. If your app needs to work on both tablet and phone factors, you may include all three components on the screen of a tablet, but only the line items and totals on a phone. You can however re-use the line item and total fragments between both form factors. You maybe also re-use the inventory fragment, but compose it differently: on tablet it's composed on the screen along with the line items and total, but on a phone it's composed on a separate screen (embedded in a different activity).
That's the dream anyway. IMHO the complexities of having a component with a complex life cycle (fragment) living inside another component with a complex life cycle (activity) make this a questionable prospect. If you keep your fragments completely stand alone with no knowledge of the holding activity or other fragments, and keep the activity unaware of details of the fragment, it can work. Otherwise you are in for a lot of "fun".
Ironically, fragments that are composed on a screen with other fragments are typically NOT stand alone. In my example above, the order total fragment needs to know the order line items. That means you need to create a service for these two fragments to communicate this information without talking to each other directly.

Why using Fragments?

I have read the documentation and some other questions' threads about this topic and I don't really feel convinced; I don't see clearly the limits of use of this technique.
Fragments are now seen as a Best Practice; every Activity should be basically a support for one or more Fragments and not call a layout directly.
Fragments are created in order to:
allow the Activity to use many fragments, to change between them, to reuse these units... ==> the Fragment is totally dependent to the Context of an activity , so if I need something generic that I can reuse and handle in many Activities, I can create my own custom layouts or Views ... I will not care about this additional Complexity Developing Layer that fragments would add.
a better handling to different resolution ==> OK for tablets/phones in case of long process that we can show two (or more) fragments in the same Activity in Tablets, and one by one in phones. But why would I use fragments always ?
handling callbacks to navigate between Fragments (i.e: if the user is Logged-in I show a fragment else I show another fragment). ===> Just try to see how many bugs facebook SDK Log-in have because of this, to understand that it is really (?) ...
considering that an Android Application is based on Activities... Adding another life cycles in the Activity would be better to design an Application... I mean the modules, the scenarios, the data management and the connectivity would be better designed, in that way. ===> This is an answer of someone who's used to see the Android SDK and Android Framework with a Fragments vision. I don't think it's wrong, but I am not sure it will give good results... And it is really abstract...
====> Why would I complicate my life, coding more, in using them always? else, why is it a best practice if it's just a tool for some cases? what are these cases?
I am sorry if I wrote too much, and thanks for your time. I hope I will get your attention, because I really need ideas and experiences about this topic.
Best regards, Ahmed
You shouldn't always use fragments. Fragments have their uses, such as when you want to page in and out parts of the screen or when you want to drastically change the UI in different orientations. When they make sense, use them. When they don't, skip them. I find they make sense in maybe about 10-20% of apps- I rarely see the need.
If there's a certain positive aspect apart from the simpler reuse of logic through different layouts, it's the ability of Fragments to be kept alive by the system at orientation change, aka while an Activity is reconstructed from zero, a Fragment can retain its instance, and therefore using them is more stable than an Activity. Also, switching between Fragments is quicker.
Personally, if I don't need to mess around with different orientations and layout sizes, I still prefer using Fragments and a singular container Activity around it, for stability and seamless switching between the different screens.
Its quite a general question and not directly related to a specific programming problem. But in my opinion good software is based on good design and therefore a good understanding and best practices. So your question is a good one for stackoverflow.
So, what about fragments. It took me a while to understand why you could or even should use them. As #pskink said, you can easily live without them. But if you are planning to rollout your software on different devices, you should definately think about fragments.
The screen resolution and density is not the only problem. Think about a smartphone. The screen is much smaller, so you can not present your app the same way as you can on a tablet. For instance a master detail flow. Left side, a list of elements and when you click one element, you will see details of that element on the right side. Easy to do on a tablet. But on a smartphone you would put the master-view into one fragment and the detail-view into another one.
You got two options to realize that scenario. Either programm different activities for smartphone and tablet but because they are actually doing the same logic, it's better practice to put the logic into fragments and reuse those fragments in two layouts (phone/tablet).

Android - repeated fragment transactions and phone resources (complex)

Preface - The code I have created so far already delivers the desired user interface, my question is about phone resources and whether there is a 'better' implementation. Also, I am relatively new to Android development and may be misunderstanding some basic concepts.
I am developing an app with tabs, and some of the tabs have multiple views. At the moment each view is managed by a fragment, and when an user is on a tab and opens a new view, the views transitions horizontally.
(the app is a port to Android of an existing iPhone app, and while the people I am working for readily understand the need to make an Android app as Android-native as possible, they want the basic user interface and control to remain the same so that if an iPhone user buys an Android phone and purchases another copy of their app, there will be no fundamental difference)
The primary tab is different however--it reloads itself. The app is essentially a study aid; imagine that each view is a card representing information, and the user if flipping through cards.
This is accomplished by having the 'card' fragment request that the fragment manager detach and then re-attach itself. This is accomplished by calling a method in the FragmentActivity that executes the following (simplified from the actual code):
FragmentTransaction ft = .... .beginTransaction();
ft.setCustomAnimations(int out,int in)
ft.detach(relevantFragment);
ft.attach(relevantFragment);
ft.commit();
.... .executePendingTransaction();
where 'out' is fromXDelta="0", toXDelta="-100%"
and 'in' is fromXDelta="100%", toXDelta="0"
Consequently, the old view slides out to the left, while simultaneously the new view slides in from the right.
This works just fine, in fact in terms of user experience it is exactly what I want. However, the fragment we are reloading has an extremely complex view hierarchy and my understanding of fragments is that the entire thing is going to be garbage collected and re-instantiated on each transition, which the user may easily invoke a large number of times (100+) while using the app to study.
Almost all of what I have read indicates I should avoid heavy object creation/collection as it will cause my app to devour an user's battery, regardless of whether processor is strong enough to perform without any visual lag.
.
ACTUAL QUESTION: Is there any way to emulate this kind of behaviour that does not force the phone to fully destroy and re-create the view every view seconds as the user clicks through?
Things I have considered:
Eliminate the transactions/animations and simply have the fragment load new information. This would be easy of course, but is not what my employers want.
Create two identical copies of the view hierarchy in the XML, and toggle them back and forth from View.VISIBLE and View.GONE, using a custom ScaleAnimation to attempt to emulate this behaviour. I'm not sure whether this would work, but at first glance it seems rather... sloppy.
This is an unnecessary and/or silly optimization that I should not be worried about, due to how the phone and/or Android system operates, and I simply don't realize I am wasting my time.
Any advice, suggestions, or clarifications on how the operating system work are much appreciated.
my understanding of fragments is that the entire thing is going to be garbage collected and re-instantiated on each transition
If you look at your code, this is impossible, at least at the fragment level. You are not letting go of the Fragment object, nor are you supplying some means for Android to create a brand new identical fragment. Hence, the Fragment will not be garbage-collected.
It is conceivable that Android will call onCreateView() again for your fragment and discard the old views, though that seems unlikely. You can test this by setting a breakpoint or adding a logging statement.
Almost all of what I have read indicates I should avoid heavy object creation/collection as it will cause my app to devour an user's battery
Done millions of times, definitely. Done "100+" times, it will not "devour" the battery. Nibble, perhaps.
Things I have considered:
I would focus on #3. At most, determine if indeed the fragment's view hierarchy is being recreated, in the form of multiple calls to onCreateView(). If it does, then use Traceview to determine exactly how much time this operation is consuming.
To summarize the discussion with CommonsWare in the comments above (and subsequent investigation of ways to address the matter), this is not a productive optimization. Preserving the view hierarchy for reuse, rather than allowing it to be destroy and recreated, only saves a few milliseconds of of CPU time. The vast majority is consumed by the phone's rendering of the views, not their instantiation.
CommonWare is correct in his initial answer (mostly). The Fragment.onCreateView() IS called every time a fragment is attached, but there is no productive way to optimize the view rendering. Nothing to be done, nothing to worry about.

Pattern "One activity, multiple views": Advantages and disadvantages

This pattern is similar to the pattern Main Servlet (the Front Controller) that is used for developing web applications.
The main idea of this pattern: we have one Activity that manages multiple views and this activity is responsible for representing current content. Not all views need functional of activity (e.g. life-cycle methods) so the main question is: if I can go without activity why do I have to use it?
I have found the following disadvantages of using this pattern:
Official source doesn't recommend to Overload a Single Activity Screen
but they don't explain why.
We cannot use TabActivity, ListActivity, MapActivity. But there are some tricks to go without them.
If different screens have different menu it's a problem to make that without activities.
It is necessary to keep history by ourselves. But it's not so difficult to develop.
I have found the following advantages of using this pattern:
It's faster to change the content of current activity than to start another activity
We are free to manage history as we want
If we have only one activity-context it's simpler to find and solve problems with memory leaks
What do you think about this pattern ? Could you provide any other advantages/disadvantages ?
We cannot use TabActivity, ListAcivity, MapActivity. But there are some tricks to go without them.
You have to use MapActivity if you want to use MapView. You have to use PreferenceActivity if you want to use preference XML.
It is necessary to keep history by ourselves. But it's not so difficult to develop.
The difficulty in managing your own history will depend greatly on what the history needs to be. Implementing history for a simple wizard will be fairly easy. However, that is a particularly simple scenario. There is a fair amount of history management code in Android that you would have to rewrite for arbitrary other cases.
You also forgot:
#5. You will be prone to leak memory, because you will forget to clean up stuff, and Android will not clean up stuff (since it assumes that you will be using many small activities, the way they recommend).
#6. Your state management for configuration changes (rotation, dock, SIM change, locale change, multiple displays, font scale) will be more complicated because now you also have to figure out what extra stuff (e.g., history) need to be part of the state, and you have deal with all of them at once rather than activity-at-a-time.
#7. Having multiple entry points for your application becomes more challenging (e.g., multiple icons in launcher, app widget linking to some activity other than the main one, responding to etc.).
It's faster to change the content of current activity than to start another activity
For most modern Android devices, the speed difference will not be significant to most users, IMHO.
If we have only one activity-context it's simpler to find and solve problems with memory leaks
Except that you still have more than "one activity-context". Remember: your activity, large or small, is still destroyed and recreated on configuration changes.
What do you think about this pattern ?
Coase's "nature of the firm" theory says that businesses expand until the transaction costs for doing things internally become higher than the transaction costs for having other firms do the same things.
Murphy's "nature of the activity" theory says that the activity expands until the transaction costs of doing things internally become higher than the transaction costs for having other activities do the same things. Android developers will tend towards a "user transaction" model for activities -- things that are tightly coupled (e.g., steps in a wizard) will tend to be handled in single activity, and things that have little relationship (e.g., browse vs. search vs. settings vs. help vs. about) will tend to be handled in distinct activities.
This will be horrible to maintain if new functionality is added later on.
I'm also not convinced it will be so much faster that the user could notice.
Having components as smaller pieces that are easier to change or swap out is definitely the way to go.

Categories

Resources