I’m not an Android pro though I’ve developed an app consisting of more than 50 activities which makes the app really large. After 8 weeks of developing, now there are problems which caused the app difficult to maintain and upgrade.
Major ones I’m dealing with are
I cannot pass object reference to activities’ constructors. In fact I found the mechanisms of startActivityForResult – Intent – onActivityResult really limiting and results in dirty code of many constants for actions per activity and a lot of switch case that is really hard to follow the flow of app.
Another problem is that I do not know how to manage the life cycle of the whole app as each activity has its own life cycle.
I had some successful experience with LWUIT and J2ME – polish which ignore J2ME MIDlets (similar to android activity) and implement their own architecture and windowing system with just one MIDlet as entry to the app. I’ve come up with the same idea for android.
To clarify, I’m thinking of an app with just one main Activity and other activities implemented as objects which extend View object and these views can be dynamically added to main activity FrameLayout and stack on each other. Activities’ logic can be implemented in such classes and I've even found a way to implement dialogs in this way.
Business and state objects can be passed to their constructor and it sounds good ignoring its side effect of writing a little more code. This way listeners can also be passed to views’ constructors which makes app UI switch and flow management easier.
But the questions are:
Is it a good practice?
Wouldn't it lead me to performance or memory issues?
I'm also aware of
Android: What is better - multiple activities or switching views manually?
Don't Overload a Single Activity Screen
Pattern one activity, multiple views. Advantages and disadvantages
None of these clearly address the issues regarding performance or practice with reasonable evidence or documented reference
Please someone help me with this
There are popular apps in market with only one or a few activities. They use fragments and switch them. I would prefer fragments over your approach. Although I think fragments are too complex for many purposes, for your use case it would be a good solution. Your UI behavior should be in fragments, and your activity is the controller part transferring data between your fragments. Fragments also have an own life cycle.
I don't like startActivityForResult either. If I have a set of activities - all providing data - and I don't know in which order they will be called, I prefer to use a singleton class then using intents for data transmission between activities. But you have to analyze your problem to get a good solution.
There is already an MVC framework built, PureMVC library.
Related
All the reasons I can find for using Fragments in Android activities have to do with having the ability to display multiple classes/view in the same screen, encapsulating multiple logical components, etc.
Considering all this, it seems, fragments are only actually useful when you employ the use of many of them.
Is that so? Is there ever a point of using just one fragment in an activity?
I ask now because I saw an option on Android Studio to do just that, and I am wondering what the point is.
Out of my personal opinion, I would say yes.
For the following reasons:
Assuming you are familiar with Fragments, creating a Fragment is hardly any extra work plus has the following benefits
Fragments can easily be reused somewhere else (possibly another Activity that has more Fragments, furthermore, Fragments do not necessarily need to use up the full screen).
Activity transitions are more expensive, Fragment transitions are more sophisticated.
The Fragment animation framework is better (in terms of usability and performance).
I always like to keep the number of Activities to a minimum which keeps the AndroidManifest.xml short and clean.
UI separated into Fragments leads to cleaner code structure and easier code maintenance.
According to google coding guidelines, it is best practice to create as few Activities as possible, and create multiple Fragments instead that are switched inside an Activity.
Well it depends, if you are going to use that fragment in another activity yea, you have a "point" and maybe in a future you can reuse it on another activity, but in the case for example of a splash screen well, it don't have a point. All depend in the uses you want to give to your application.
Pros:
-> reusable piece of code
easy to utilize it again in any module
easy to debug
-> handles orientation changes better than activity using setRetainInstance(true)
-> great help when scale the app in future for multipane layouts or multi-screen support
Cons:
-> little overhead and time consuming if you are not familiar with fragments
Many Android apps include a BaseActivity class of their own, which all Activities in the app extend. This is useful because it gives a central place to put functionality that's common across most/all activities. The main drawback of having a BaseActivity is you are then unable to use any of the Activity subclasses (ListActivity, etc.).
One alternative is to have an ActivityDelegate. This gives a central place for functionality while still allowing you to use Activity subclasses. It's also arguably more testable, since it uses composition instead of inheritance.
Both of these solutions potentially lead to a lot of spaghetti code when the BaseActivity/ActivityDelegate gets too large and convoluted. A possible solution to this is to use the delegate pattern, but split the functionality into many different Delegates. This reduces spaghetti code in the Delegates, but then the Activities get more complicated - they're now trying to forward their on* methods to lots of different Delegates instead of just one.
A possible solution to all of these problems is to use a Delegate Manager. The Delegate Manager keeps track of all the smaller Delegates in the app. Activities forward their on* methods to the Delegate Manager, which forwards them on to all of the individual Delegates. This accomplishes all of the following:
Dedupes code - all common functionality gets placed into one of the Delegates
Allows use of Activity subclasses
Simple code in all Activities - all on* methods are forwarded to just one class
Easily testable - it's simple to mock out everything around the Delegates and the Delegate Manager for unit tests
Has anyone tried using this pattern before? If so, how did it go?
As far as I understand, you're talking about one single DelegateManager object for the entire application. If this is the case, you can use registerActivityLifecycleCallbacks, see http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks%28android.app.Application.ActivityLifecycleCallbacks%29
If you're on < API level 14 you need to take a look at: https://github.com/BoD/android-activitylifecyclecallbacks-compat.
registerActivityLifecycleCallbacks lets you hook into the activities onXXX lifecycle methods.
Doing this certainly has all the benefits you described:
decoupling being usable only when you actually need to repeat behavior which is kinda seldom for controller+view logic tied in together the way Activity works.
Removing inheritance is nice if you have activities you might reuse - but I've never had to do it before. But I guess a good use-case would be your home-cooked activity for handling settings or something like it that needs app-wide L&F & behavior.
On the top of my head I can think of these downsides:
Using listeners all over the place can blur path of the application activity/call hierarchy and can make the code hard to understand. This holds true for all listener/dispatcher type of programming. It's a powerful tool, but handle it with care.
It can introduce a lot of (as you mention) boilerplate/spaghetti code if all you do is pass on to lifecycle listeners/delegates.
it is your responsibility to de-register yourself from the Application with Application.unregisterActivityLifecycleCallbacks. I don't think there's a good way around it,
Personally I haven't used this design-pattern much for lifecycles, but it might be worthwhile for some use-cases. For example:
ApplicationLifecycleLogger: Every time you create/resume/pause... an activity, you logcat or something else making debugging lifecycles a tad bit easier.
If for example someone goes into an activity he/she is not allowed to go into due to model state of some sort (e.g. a ringing alarm -> can't go into AlarmEditActivity), you could do finish() there.
Passing object state across activity boundaries without Parcelable:s and screen rotation changes. Usually this is implemented with a Map in Application or some static field somewhere. You can do this by letting the delegators hold state.
Also, take a look at: Is there a design pattern to cut down on code duplication when subclassing Activities in Android?
I hope this was helpful =)
Given the fact that I don't have very extensive experience when it comes to Android apps, I have a questions regarding the architecture of an application :
Are there any problems I can run into if I decide to create an application that has only one activity and I 'load' all the other content using fragments only ?
Thanks
No, this approach is absolutely all right. More than that, Fragments are more lightweight then Activities, so you can gain performance by using this approach. However, keep in mind, that Activity is designed to behave as a single user screen that serves for a concrete purpose, and Fragments are the parts of this screen. So your approach works well if the whole application should contain a single user screen according to the design, thus serving for a single concrete and properly defined purpose.
I have a full-fledged app which is NOT developed using Fragments. My confusion is that should I change it to have Fragments instead of Activities. The thing that I would like to tell is that I'm using only portrait orientation in my application and it is built, keeping in mind only phones, not tablets. So my question is, will it do any good if I change the whole structure of app and use Fragments.
As far as I know, Fragments should be used only If we want to reuse something. Any suggestion is appreciated.
Fragments can be used to create a dynamic and multi-pane user interface, and as such are ideally suited for tablets which have a lot more screen real estate to use up. Of course, on a phone the situation is a little different, you have a much smaller space to play with and sometimes it can be a struggle just to get one Activity fitting onto the screen without worrying about including multiple Fragments.
Fragments are very good for dynamic interfaces, and for helping with compatibility between Tablet and Phone. They are also able to communicate with each other much better than Activities can, so there are certainly advantages to using them even on a phone-only setup. (See FragmentsManager for some functionality they can be used for)
One example of use is illustrated in the diagram below (taken from Android Developer site)
This illustrates the flexibility of the Fragments, which on tablet can occupy the same screen, switching to a more Activity-like format on a phone. It is this kind of power that gives the Fragment such an advantage over an Activity.
So clearly there are advantages to switching to a Fragment orientated solution in terms of flexibility, but your original question states that you are targeting phones only, and only in portrait orientation.
Having an application that is already in existence with Activities, providing that it is a solution that you are happy with, and has good usability I would say there was no reason to switch to Fragments (unless you are looking for a challenge or have some spare time and fancy a tinker). While advantages exist, a drastic change such as adding Fragments could introduce bugs into your application and impact the user experience (at least for the short term).
Long term, if you are ever considering bringing tablet support into the fold or would like to use the landscape orientation, then it might be a good idea to start looking at what you can do with Fragments to improve the experience, and integrate this with the current flow of your phone application.
Otherwise, the current solution you have created will more than suffice, and as long as it is well received by your customer base I see no reason to change.
Of course, there is no harm familiarising yourself with the Fragment APIs for future projects, or in the event that it is time for a refresh of your current project's UI.
It is worth pointing out that Fragments are only supported natively from Android 3.0 (API level 11), and to support earlier devices you will require the Android Support package found in your installation. As such, if your current application targets 2.x devices, I would stick with an Activity based approach, for simplicity and .apk size, unless moving to a native API Level (like Android 3.0+). This is personal preference though and ultimately the answer to your original question will boil down to your personal preference.
Think of fragments as a way to modularize your code into manageable pieces. Each fragment represents a small piece of functionality and UI. This allows your to easily adjust your code to fit different scenarios.
Sure you don't plan on supporting tablets now (regardless of how you feel tablet users will install the app), think of larger size 5-6" devices and the potential of extending your app over to them. It is best to provide your app to as many devices as possible and the best apps will tailor the experience to the device.
The transition to Fragments doesn't have to be difficult. Take a small piece of functionality and move it over to a Fragment. Then you will see how easy and flexible the new pattern is. You don't need to rewrite the entire application as Activities and Fragments can work together.
I believe by skipping out on Fragments you are really making your development tasks much more difficult in the long run.
If you don't plan to support tablets in the future than leave it as it is. You won't gain anything when you convert your app to fragments.
The situation is different if you start a new application. I would use fragments from the beginning in order to be more flexible should the need arise to support other form factors in the future. Note that the functionality is available in the support library so you can use it also on older devices.
It is easier to set interaction between fragments than between activities.
In case of activities:
You need to use startActivityForResult()/onActivityResult();
Your custom types must implement Parcelable interface in order to be passed between activities;
You have to free all resources when your activity is paused/stopped.
In case of fragments:
Passing data is as easy as getting an instance of fragment from FragmentManager and calling a method on it;
No need to implement Parcelable;
You can hold references to "heavy" resources in activity which contains all of your fragments and initialise/release them only once (no need for initialisation/release for each fragment).
Also, an instance of Fragment is more lightweight than instance of Activity and takes less time and resources to be initialised/resumed.
In general, interaction between the components of your UI is cleaner, more elegant, easier to implement when you use fragments.
As far as your application or any of the application is concerned , it's better to use fragments and it causes no harm to your application and it also ease your burden while further extending your application for tablets also.So, better to start with the use of fragments in your application.
I've just finished converting my application to use fragments, because:
Wanted a tablet version
Wanted to use ViewPageIndicator and ViewPager with advanced views
Those are the most compelling reasons to use fragments.
It might be a little more work, but with significantly more tablets appearing on the market and fast adoption rate, perhaps it's worth considering supporting tablets with a nicer UI?
If you really don't want to do this and have no requirement for view paging using advanced views then there is no point over-engineering your project to make it use fragments for using fragments sake. You could argue you might learn about them, but when you come to use them in your next project, you can learn then (that is what I did and it worked out fine).
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.