Introduction to Single Activity Applications
Since the creation of the ‘Fragment’ class many developers, including me, started asking when to use Android Single Activity and when to use Fragments. Android documentation says that Activity is for “a single, focused thing that the user can do” with an app, but what does it mean? It looks like this is kind of outdated. Today’s applications, even Google ones (like Gmail), contain side menus or detail views as Fragments (like the e-mail details page in Gmail) which gives more than a “single, focused thing”.
So the question is, why not make an application that contains only one Activity and many Fragments? It looks like it may give a lot of advantages:
- Toolbar configuration and view in one place
- greater control when changing content (with Activity we have to rely on the Android Framework)
- lower memory footprint (previous Activities with views exist in stack, which can cause an out-of-memory exception in endless navigation applications)
- side menu in all application views (if needed)
So, let’s see it!
At the beginning, it looks really simple. We create one main Activity, with a Toolbar (we could also move the Toolbar to a Fragment) and a container view below it. Then, using
FragmentManager, we replace Fragments in that container and in addition we add the Fragments to the back stack, so the back button will work.
The first thing that you will have to do is handle Toolbar updates. Now we have the Toolbar in the Activity, but the content Fragment should be able to change the Toolbar’s content. We will have to create some Toolbar model representation – let’s say
ToolbarConfiguration – that the content Fragment will reference. With this, the Fragment will configure ToolbarConfiguration, which will then be sent to the Activity and the Activity will handle it properly.
In addition we need to somehow inform the main activity when the content Fragment wants to show a new Fragment. There are two ways of doing this:
The first is to use a delegate pattern and to create for each content fragment a delegate field that should be set by the main activity. In that delegate there would be a method like
onLoginButtonClicked, which will be called when the login button is clicked and the main activity will change the content Fragment to LoginFragment.
The second approach, which I prefer, is a propagating event approach (we could also use Event Bus, but we really don’t like it). In that approach we are propagating
LoginNavigationEvent to the parent Activity/Fragment. If the parent can’t handle that event it propagates to its parent Activity/Fragment and so on.
At first sight it looks really easy, but if you don’t have a good knowledge of the Fragment lifecycle and how Fragments are maintained in the back stack you could run into many problems.
The first thing that you have to remember is that when you replace a content view with a new Fragment, the old one isn’t destroyed and is not freed from memory. It is still alive, but its view gets destroyed (
onDestroyView() called). Now, when you move back to that Fragment (tapping the back button) the old one is reused, and a view gets recreated (calling
What does this mean? You have to be careful what is initialized in
onCreate() and what in
onViewCreated(). As an example look at
RecyclerView and its
Adapter. In that case the
Adapter should be initialized in
onCreate() and set on
The second big thing is intent handling. With many Activities it is easy – you are creating intent filters for specified Activities and voilà (yeah, I know that this is for simple cases, but let’s assume). As for single Activity per app, this Activity will need to handle all intents and will have to decide which content Fragment to show and what should happen when the up button is tapped in that Fragment. It can be tricky.
There are a lot of other problems, like possible memory leaks that could happen or child Fragment animation glitches so be aware of that.
It is hard to say which way to choose in every case. As for me, the biggest advantage of single Activity in an Android app is that we have full control of what is going on in the app, especially when we want to make fancy animations between content views. Naturally, with all that control you will need to spend more time doing this in a way that you like. You can use a mixed approach, of course, where some of the functions are in a separate Activity (like composing an e-mail). It is all up to you!
Staff Software Engineer