This question already has answers here:
What is the benefit of using Fragments in Android, rather than Views?
(6 answers)
Closed 10 years ago.
What is the advantage to using Fragments over using custom Views that are reused in different layouts?
In the original blog post introducing fragments, Dianne Hackborn says that
[Fragments] make it easier for developers to write applications that can scale
across a variety of screen sizes, beyond the facilities already
available in the platform.
and she goes on to explain Fragments in the context of making a tablet layout for an app that combines the UI of two activities from the phone version of the same app.
But it seems that the same reuse could be achieved using custom Views. The main different between Fragments and Views seems to be that they have differing lifecycles...
The Fragment lifecycle is:
onAttach(), onCreate(), onCreateView(), onActivityCreated(), onStart(), onResume(), onPause(), onStop(), onDestroyView(), onDestroy(), onDetatch().
The View lifecycle is:
ctor, onFinishInflate(), onAttachedToWindow(), onMeasure(), onLayout(), onDetatchedFromWindow()
I'd like to hear from developers with experience writing large apps about what benefits (if any) they've seen in using Fragments vs custom Views to divide up the UI into reusable pieces.
The main reason is that fragments are more reusable than custom views.
Sometimes you can't create a fully encapsulated UI component relying on views alone. This is because there are things you would want to put into your view but can't because only an Activity can handle them, thus forcing tight coupling between an Activity and a View.
Here is one such example. Lets say you want to create a reusable UI component that, among many things, want to capture a photo and do something with it. Traditionally you would fire an intent that starts the camera and returns with the captured image.
Notice that your custom UI component can't fully encapsulate this functionality because it will have to rely on hosting Activity's startActivityForResult because views don't accept activity results (they can indirectly fire an intent through context).
Now if you wanted to reuse your custom UI component in different activities you would be repeating the code for Activity.startActivityForResult.
Fragment on the other hand cleanly solve this problem.
Similarly your fragment can contribute items to your options menu, something traditionally only an Activity could do. Again this could be important if the state of your custom view dictates what goes in the menu.
A fragment is way more than just a view. In fact it can even be totally without a view. It can have all sorts of stuff in it including AsyncTasks, various Listeners, file and database access and so on and so on.
Think of it as a small activity, but you can have multiple of them on the screen and work with them all including communicating with each other while they are visible.
E.g. you could have a list of shopping cart displayed in one fragment and the currently selected cart in detail in another fragment. You then e.g. change the quantity of an item in the detail view and the list view could be notified about it and update the total price in the list view. You can totally orchestrate interactions like that nicely while e.g. still having only one of them visible on a smaller screen device.
I have refactored a large business app (>15 activities) from activities to fragments to get good tablet support and I would never start a new app without fragments.
Update Feb 2016: While the above still holds true, there are complexities with fragments that caused many people to entirely avoid using them. Newer patterns such as usage of MVC approaches and more powerful views provide alternatives. As they say .. YMMV.
Some description:
Imagine Activity as a plate that hold one big cake.
Fragment would be a container that slices the same cake into pieces.
Each slice contains it own logics (listeners, etc).
And in total they are almost no different with the one big cake.
The benefit:
When you plate can't hold a big cake. (Screen is small) You can easily use a a few plates (Activity) to hold each of them WITHOUT the need to move your logics into the new activity.
Better re-usability. I have some instances where I could reuse a fragment entirely in another App. You might claim that a custom view could does that too. But refer to point 1, I could reuse it with just few lines of layout changes but for a custom view, it have to find a way to plug it into both layout and code.
It is, in some sense, a more OO ways of organising your UI logics in Android programming. When you have a feature (A new partition on the screen for example), you create a new Fragment class, with minor modification to existing activity class. However if you are programming only with activity, you will need to add logics and make big modification on tested class.
Just my 2 cents. :)
The lifecycle methods are probably your biggest hint. If you think about it, they correlate closely to the activity lifecycle (with some hooks into the activity and views). In fact, in the article you linked, Hackborn says:
In some ways you can think of a Fragment as a mini-Activity
As with many things in software design/development, there are a multitude of ways to do things. There are many different places you could put your code. Yes, you could probably put a lot into a view, but keeping different concerns separated in different classes is a good thing though. The classic pattern of this is MVC and it applies in this scenario. You don't want to bake in too much controller logic into your view. It's better to keep it in controller-like classes which are the activity and now the fragment. This is why the fragment's lifecycle is more like the activity's than the view's--it was made to facilitate this kind of organization.
I touched Fragments once and found them not very useful (see this post). From what I have read, A Fragment is really a fancy word for an Object with access to Activity Context. I like to ignore Fragments in my work, and just create these Objects myself. I have created very large, very demanding apps by passing an Activity to constructors, instead of Context. One major benefit, however, for using Fragments is that they are supported by the View layout system - so you can easily add them to Android xml (if you use it for your layouts).
Custom views are much more work than just using fragments in place of your activities. if you decide to use Activities and custom Views, you have to create your custom view, and then you have to implement the same activity lifecycle methods in your activity (a very similar lifecycle is used for fragments).
Using Fragments also allows you to separate components into their own classes (Fragments), rather than having too much logic in a single Activity. Let me ground that with an example:
Say you're implementing a magazine reader application. using fragments, you could create a fragment: ArticleList, which displays a list of articles, and another fragment: ArticleDisplay, which handles the logic for displaying content. you can then specify how these fragments should interact using the fragments tools, so that on a handset, you can use the full screen real-estate for ArticleDisplay, while on a tablet, you can display the fragments side by side.
If you were to attempt this with an Activity/custom view, you'd have the logic for both Fragments in your monolithic Activity, you'd have to write a custom view, and you'd have to debug this unwieldy monster.
Fragments are, in general, a more sophisticated and powerful way to write your applications. They can do everything an Activity can do, and more. If you don't need the extra functionality, the defaults will probably get you where you need to go, and with less work.
Related
I have a NavigationView used as a slide-in menu. Each of that menu items is a use case itself, therefore I tend to using activities containing different fragments.
But nearly every example of NavigationView/NavigationDrawer uses fragments, so I don't know what to use here.
I thought different use cases should be "encapsulated" in own activities, therefore I don't really understand why Navigation[View/Drawer] uses fragments. And that leads me to my question: for a Navigation[View/Drawer] containing completely separate use cases - should I link to activities or fragments?
I posted a similar question
I have created around 4-5 apps with mid-big size project. I used Fragments for Navigation Menu clicks and had to manage lots of Lifecycle events and Memory Leaks and shit stuff. The Performance degrades and app becomes slow.
Then in one of the app I Used Activities for each Navigation menu clicks, treating it separate Entity/Module. This Activity would then use fragments if they had child views.
Doing so I had a great app, less trouble and I could concentrate on Business Logic rather than maintaining fragments.
Although Google recommends Fragments, But I never liked them, they always put me in trouble and handling them is a mess.
In my current Project I have created a BaseActivity implementing Navigation and all the other Activity extend it.
the NavigationDrawer and the contents are all just Views inside the Activity view hierarchy.
The use it of fragments is usually shown in tutorials because you can encapsulate each item inside a fragment, and fragments is the usual Google advice, even though they're a pain in the ass and have horrible drawbacks regarding animation.
But the direct answer to your question is: It's all just a matter of structure and organisation and it really does not matter how you do it, because in the end they're all just views in the Activity view hierarchy.
You can "manually" inflate views and put in the content area.
You use fragments to separate the views and logic and their own container.
You can use activities with different content and the same NavigationDrawer.
I am planning an app and trying to explore all the possible development options/methods I have available. One thing I'm struggling to get my head around is Fragments. I see a lot of people praising them as you can "resuse" fragments throughout the app but I can't think of an example situation.
From some example apps I have looked at (all been tabular layouts) the code for each fragment has one layout, so why not have a seperate activity instead?
I am hoping to implement a tabular layout in my app. If anyone can give me an example of a fragment being reused within an app I hope it will give me a better understanding of the benefits.
"Reuse" is overrated. Of course - you can put this same fragment (with this same features) in different places of your application - let's say that you can use a fragment in different, horizontal and vertical layouts (as you probably saw in Google's tutorial).
But at the end using fragments simplifies your project - for example - you can switch fragments inside one activity and get benefits of much easier navigation and in app communication.
Using fragments gives you one more thing - flexibility. It's much easier to move some view from one place to another, or just remove from application. All that because fragment encapsulates logic and usually a view, still offering power of externally managed lifecycle.
(Thanks for comment from Richard Le Mesurier)
Fragment is not a View neither a ViewGroup. It is not a visual element at all. Fragment inherits directly from Object.
One should think of a Fragment as a unity of a reusable code, reusable in various Activities (the Activities consist of visible elements).
Thus if you can think of any code you can reuse through several Activities (even the same Activity with different layout) and that code somehow depends on Activity lifecycle, then you probably should make this code a Fragment.
I've read Activity and Fragment sections of Android API and many Q&A on these two, but I still don't have a clear understanding of some points.
When android SDK creates an activity for me, it also creates a fragment for it. From what I know I can bind several fragments to one activity and switch them as I like. But I don't understand if I ever have to add any components to activity xml file? I mean all layouting and buttons are in fragment xml. In what situations and why would I need to use activity's xml file? Can I make buttons, for instance, both in activity xml and fragments xmls? Is it a good practice?
What logic should be generally implemented in activity class and what in its fragment? For example, I think that Fragment class is needed only to get data from UI and pass it to activity. Is that right?
Thank you for your patience
An activity is basically a screen in your application (think of it as like a webpage) with all associated logic. A fragment is a sub-activity, a portion of an activity with its own set of logic and UI.
You should use a fragment when either you use the same UI in multiple activities, when you want large parts of your activity's UI to change in and out as people take actions, or when you want to rearrange large parts of your UI in different layouts. When none of those are true you should ignore fragments and just use activities directly. In my experience it ends up being about 80% activities and 20% fragments, but it really depends on what type of apps you're developing- tablet apps use a lot more fragments, for example, because they have more screen real estate.
I'm writing an app for phones and tablets. Like the Contacts app, there are multiple tabs (2 in my case). For the phone UI, they're managed by a ViewPager, with a fragment for each tab.
But for the tablet UI, each tab is an activity, rather than a fragment. They have to be, because you can't put fragments inside fragments. (Right?)
I realize I could just call setContentView() on the tab listener, but wouldn't that destroy the activity every time it was changed? I'm confused by a lot of this.
What's the best way to do this without breaking my phone UI?
A well designed tabbed UI never uses Activities for tab content.
You're correct in that you cannot nest Fragments in the current implementation, but that doesn't mean your only alternative is Activities. Tabs should always act as a view switch; a tab switch never creates navigation history and tab navigation should always happen within the same Activity.
Remember that Activities and Fragments are just controllers from an MVC point of view. They exist to respond to lifecycle events and manage elements of your application in response to those events, including views within your UI. The content of your UI is wholly determined by the view hierarchy of the current window and you can manipulate the view hierarchy in whatever way makes sense for your app. (While preferably still following the design guidelines!)
Since Fragments have a built-in mechanism for managing a view sub-hierarchy they're often a natural choice for factoring your UI but they're not the only way. ViewPager PagerAdapters can manipulate view sub-hierarchies by inflating them from the resource system, recycling views the way a ListView does, or any other mechanism you can come up with and not use Fragments at all if the lifecycle events they provide aren't needed. Different layout resources may include or exclude certain elements based on screen size using different layout variants for different resource qualifiers.
In short, don't get stuck on the idea that Fragments are the only way to do multi-pane UIs, or the only way to implement each page of a ViewPager. They're powerful options for both, but depending on the information architecture of your Activity you may find yourself using them in a different way than another app and that's OK.
Overall, if you're having trouble determining where the logical cut points are when factoring your Activity's UI, you may be building an overall UI for your app that is going to be as awkward to use as it is to implement. Let the UI design guide your implementation. If each tab is naturally switching out the entire content of the Activity window, then each tab might be well suited to a Fragment. Perhaps those Fragments in tablet mode expand their capabilities and present more than one pane in their respective layouts using different layout resources.
I've recently decided to update my app to support the new fragments feature in honeycomb 3.0.
My Application currently works on a list view that opens different activities depending on which list item is clicked.
Using an adaptation of the code in this tutorial I have created an app that consists of only two activities, but depending on which list item is clicked the second "viewer" activity launches using a different layout xml.
Unfortunately I haven't been able to figure out how to call the old methods that had all the functionality. Should I Import all of my old activities and then call the methods into the viewer activity (I may need some advice on how exactly to do this) or should I just put all the methods directly into the same viewer activity (please consider the size of these methods(which is very large by the way)).
Once everything is working with two activities upfront then it will be a pretty simple task of "fragmenting" the app as demonstrated here
Although I haven't considered that there might be a way to allow multiple fragments to occupy the same space in an activity(If this is the case then please let me know how it's done)
Thanks
As James has pointed out you will have to move the business logic from your Activities to your Fragments.
To handle events you can create a listener Interface. The CONTAINER activity/ies will implement this interface. As fragments has access to the container activity you will be able to delegate to the container Activity the "logic" for the desired events. For this events the activity will decide whether to launch a new activity, show/hide new fragments or whatever.
I had a similar question, take a look to the question and answer: here
Although I haven't considered that there might be a way to allow multiple fragments to occupy the same space in an activity(If this is the case then please let me know how it's done)
I think its possible to allow multiple fragments to occupy the same space in an activity. Again, take a look to the answer here ... I think the concept/scope of Activity has change a bit and now an Activity can contain different Fragments which every one will allow user to do a single focused thing.
I'm not sure what you mean by "call the old methods that had all the functionality". You'll want to rewrite all of your activity classes as fragments. Check out this tutorial here (it's very concise). Basically, you'll want an activity that consists of a ListFragment and a FrameLayout. Your ListFragment will update the FrameLayout by changing to the appropriate Fragment based on which row was selected.