“Applications” in Android are .apk files that hold a collection of loosely coupled components. Rarely do components have direct communication with each other. Instead, Intents are often used to trigger these components to start. Components like Activities and Services also have a lifecycle which is heavily controlled by Android. Meaning the components may exist one moment and be gone the next depending on what the user is doing (hitting a Back button) and what resources (like memory) Android has available to it. Most people learning Android are quick to pick up on these facts. However, in these facts is a subtle problem that doesn’t come up until one starts to build their first application, and that problem is where do you put data that needs to be available to all components and has to be always available as long as one component is running? In other terms, where does one put “global application state” or “global data” in an Android application?
You could persist, via file or database (like SQLite) the data, but then getting at and updating the data is a bit slow. Further, application state usually doesn’t need to survive past the application’s process. It only needs to survive past individual components.
You could also pass information from component to component using Intents. This isn’t very convenient and the data being passed around may not be used by each and every component. Furthermore, given the fact that the application component’s lifecycle is often in the hands of Android, you cannot guarantee that the component – like an Activity – is always going to be around to be able to provide the global data. The component that is here now, may be gone in a second and with it the application state.
If you take a look at the Application class (see here) in the API reference guide, you get a suggestion on how to manage global application data. The Application class, it says, is the “Base class for those who need to maintain global application state.”
Creating the Application
So how do you create an Application to hold state. You need to do two things: create the Application class and then add the Application class to the Android manifest.
The Application Class
Begin by creating a class that extends Android’s android.app.Application. Android creates an instance of this class when the application is started – that is when a DVM process is started to run your apk. As an example of how the Application works, let’s assume that we are building some type of game. Our game application will have several screens – each screen in this case being an Activity. Players of the game generate points on each screen and their score needs to be tracked across the many screens of our hypothetical game. In order to track the user’s game score across the many Activities that make up the game, we need a place to store the game score for the duration of the game – that is for as long as the application process is running.
The Application instance is a perfect place to store the game score. Below, is an example extension of the android.app.Application class for this purpose.
Not shown or used in our hypothetical example are several callback methods defined on the Application class that may be used in your application. In particular, the table below lists some of the interesting callback methods that may be useful in your system.
|onConfigurationChanged(Configuration newConfig)||Called by the system when the device configuration changes while your component is running.|
|onCreate()||Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created. This could be used to allow you to setup the application’s state prior to running any components.|
|onLowMemory()||This is called when the overall system is running low on memory, and would like actively running process to try to tighten their belt.|
In the Manifest File
With the custom Application class now defined, it must be registered in the manifest. Use the android:name attribute on the <application element> to register your custom Application. Below, note line 12 of the example AndroidManifest.xml file that registers the GlobalState class above.
Using the Application Class
With a custom Application class created, we can use it to track the game score across the many Activity screens in our game application. In the Activity code below, note how the current score is retrieved from the GlobalState instance and used to populate an EditText field (lines 24-25). Lines 29-31 are used to update the score in the GlobalState with a new score – one that can again be shared with all screens.
For those interested in experimenting with the Application class and seeing how global state can be managed via your own implementation of the Application class, I have provided a little demo application that has two Activities that use and display the game score data as expressed in this post. Download and play with the app here: www.intertech.com/downloads/DemoApplication.zip.
How about good ol’ Singletons instead of Application?
If you read the API documentation on Application further, you will undoubtedly see the following statement:
“There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a
Contextwhich internally uses
Context.getApplicationContext()when first constructing the singleton.”
This has caused many developers to wonder whether they should use and extend Application as I have described above. Instead, you may choose to create and use an implementation of the Singleton pattern in your Android application. You will find a bit of an argument among Android developers regarding this topic. I won’t rehash the argument but instead point you to this Stack Overflow discussion (see here) which I think explains the arguments and provides additional links to other opinions. Another set of good arguments in favor of Application over Singletons can be found in this post (see here).
My thanks to Steve S., one of the students this week in my Complete Android class, for asking the question and prompting me to write this post. Many of my blog posts are driven by great questions on the part of my classroom students, but if you have a question you would like answered in this blog, send me an email at firstname.lastname@example.org. If you have a need to learn Android, please contact Intertech (1-800-866-9884) and sign up for our next class.
I’d also like to promote my talk on Android Testing coming up in June 2013. You can come here the talk live in Eagan, MN or via Web conference. Sign up today here.