What is the role of the Activity class in MVC? - android

I know there have been quite a few questions about this, however, I'm still struggling to understand what role the Activity class should play when implementing the traditional Model-View-Controller design pattern on Android?
My gut feel is that it should be the Controller, however that means a one-to-one relationship between UI screens (since you must have one Activity per screen) and controllers, which defeats the point of MVC's loose coupling between the different components.

You are right. The xml interfaces could be defined as the View and your other class working with data as the Model.
The activity receive all the events and user inputs from the View ,so, we can easily said that it is the Controller.
But let's be clear , it's not a perfect (does it really exist ?) MVC
Have a look to this question , and more specifically , the first comment of the accepted answer, it may be useful

Activities can make competent controllers and, with fragments, you can also implement hierarchical MVC. Most of making MVC work is up to the programmer, because even in the strictest frameworks you can still find ways to do crazy things.

Android does not have a good architecture and it does not follow the MVC design pattern.
The best way to conceptualize Activity in MVC is as a View (with some controller logic) because it gets destroyed every time that a configuration change happens, such as a screen rotation or locale change, losing all its state.
The controller in this case would be the Application object, because it is your bridge to access the view (Activity and its GUI components) from code outside the Activity context. You have to use singletons so that there is only one Application object at a given time, otherwise there will be one Application object per process.
The Application object is not a good place to store the Model because its life cycle is detached from that of the Activities. It can get destroyed and recreated at any point of an Activity's life cycle (while the application is in the background) without causing it to restart, and then all its variables and references not assigned inside its onCreate() method will become null.
The Model therefore has to be stored on a GUI-less, headless fragment with setRetainInstance(true), that is linked to an activity, and has to be re-attached to it every time the activity is recreated. You have to use a fragment manager to ensure you are recovering the retained fragment and not creating it anew. This is also the best place to run background tasks, though you can also run them in the Application object. Never run tasks on an Activity as they will get destroyed on configuration changes.

I think the confusion may come in with defining a view as XML and so the Activity is mistaken for being the view. It's not. You pass the view (your XML layout) into the Activity which will then inflate the views contained within the XML layout. Your activity also passes data (models) into your views (EditText, TextView, extended version of base views, etc).
If you really want MVC then you can achieve this simply by setting up your view in an XML layout, create a view object which extends from your root view (if it's a RelativeLayout extend from that). From there you add your accessor methods and different logic needed for that view and you can then add unit testing around that.
In the Activity you will no longer pass in the ID of the layout and will instead do something like this:
CustomView customView = new CustomView(...);
setContentView(customView);
...
Of course almost all apps won't do this and you really don't need to do this. Calling findViewById is enough to link to that view object and call on the methods it has. Which in my mind, is MVC.

Related

Use one activity : inflate a new layout for each view or use fragments

I am working on android application and some team members suggested using one activity and one parent layout for the whole application and each time we need a new screen we just inflate a new layout in the parent layout and destroy the old one.
I on the other hand think that using fragments would be the way to go.
Do you think one way is better than the other?
I would be grateful if you can think of solid arguments to support your claim.
Thank you
UPDATE:
We are using MVC in our application. They want to create a new class for the view while i opted for using the fragment as my view. As it stands now the application has one activity and one layout. To change the view we are calling the same layout,removing its child views and inflating the new view .I dont see how that would be better then just using the fragments as views
I think most Android developers will tell you to use one or more Activities or Fragments. But why?
Basically, because one Activity which is responsible for each and every View in your app would be something like a "god object". This is considered an antipattern, I suppose because it may fast become a maintenance nightmare.
The Android pattern of one Activity and several Fragments on the other hand is following the Single Responsibility Principle, so your code is easier to maintain. All the more so because Android-specific things like saving state on configuration change are much easier to implement if you are able to use the built-in methods.

Activity and fragment relations

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.

Views communicating with fragments

I am trying to make a sudoku application. It's a fragment based design, in which a fragment hosts a custom view which is a board. I am trying to learn how to build an effective communication within FragmentActivity, Fragment and View
Although a view is created using the FragmentActivity context and I can catch a reference to that context within the current view and then call methods inside FragmentActivity I don't want to tie views so directly to a fragment activity. Instead I want to tie the view to use methods inside a fragment. How can i do that, I can I capture a reference to a fragment and call methods inside that fragment from a view?
First of all, I strongly recommend that you read through the documentation on Fragments, as you clearly don't understand the whole concept/purpose of using Fragments in the first place (which is OK, because they are confusing the first time you learn them :P).
A lot of your question doesn't make very much sense to me, because I'm not sure what the View you are speaking of refers to. What I can tell you is that Fragments have their own UI/layout, along with their own separate lifecycle. So it sounds like you don't want your FragmentActivity to interact with the Fragments layouts/methods at all... instead, you should implement the UI's behavior and layout inside of the Fragment itself. That is, the Fragment will be in charge of updating the UI, receiving click/touch events, displaying information on the screen etc. The FragmentActivity will simply hold a reference to the current Fragment(s), and will be in charge of displaying/swapping in and out new Fragments as necessary (via the activity's FragmentManager).
Hope that answers the question somewhat... read through the documentation a couple times, it sounds like you are just misunderstanding the theory/purpose behind Fragments.

Why use Fragments? [duplicate]

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.

Is there a performance lose (or memory leak) by storing widgets in an Application?

I have a SlidingDrawer that is referenced in all of my activities. The drawer is quite detailed and has a deep hierarchy of views. Currently I have all of my activities calling the application context upon creation to receive the singleton copy of the drawer. When an activities onPause is called, it removes the drawer from its top level ViewGroup. This works, but I don't know if it is the best way of doing it.
Also an issue I'm having is context usage. The SlidingDrawer has some buttons that fire off some dialogs. Knowing that I can't pass the application context, I just created a OnActivityChangeBroadcaster and Listener which changed the references context for the drawer. But even with this the dialog always appears in the launcher activity.
Does anyone have any thoughts or wisdom on the matter?
This works, but I don't know if it is the best way of doing it.
You are leaking memory. Never pass widgets between activities. Never put widgets, or anything else with a reference to an activity, in an Application object or static data member, unless you are going to null out that reference when the activity is destroyed.
Does anyone have any thoughts or wisdom on the matter?
Recreate your drawer in each activity, please.
My approach would be to decouple the UI from the data. If many of your Activities use the same SlidingDrawer, I would separate the data that the SlidingDrawer is displaying into its own [non-UI] class so that it exists in only one place, and have each SlidingDrawer instance populate itself from that data. You can define your SlidingDrawer in XML once and <include> it in the all the layouts you need.
Then I would have one function that populated the SlidingDrawer with the data from your separate class (accessible via a singleton object or by making the data static). To achieve that you can either make a static method that takes the SlidingDrawer to populate as a parameter (public static void loadSlidingDrawer(SlidingDrawer destinationView) {...}), or you can extend SlidingDrawer and make that a class method accessible by each instance.
CommonsWare is correct, you'll be leaking memory all over the place with your current strategy. UI elements need to have the flexibility to be destroyed and recreated constantly, so it's a really good habit to get into to separate all your data into non-UI classes that you UI simply accesses to display. This decouples everything nicely and allows the framework to function efficiently.

Categories

Resources