Android’s Application Class

globalstate“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.

   1: import android.app.Application;
   2:
   3: public class GlobalState extends Application {
   4:
   5:     private int gameScore = 0;
   6:
   7:     public int getGameScore() {
   8:         return gameScore;
   9:     }
  10:
  11:     public void setGameScore(int gameScore) {
  12:         this.gameScore = gameScore;
  13:     }
  14:
  15:     public void incrementScore(){
  16:         gameScore++;
  17:     }
  18:
  19: }

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.

Callback Method Description
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.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   3:     package="com.intertech"
   4:     android:versionCode="1"
   5:     android:versionName="1.0" >
   6:
   7:     <uses-sdk android:minSdkVersion="14" />
   8:
   9:     <application
  10:         android:icon="@drawable/ic_launcher"
  11:         android:label="@string/app_name"
  12:         android:name="GlobalState" >
  13:
  14:         <!-- component definitions -->
  15:     </application>
  16:
  17: </manifest>

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.

   1: package com.intertech;
   2:
   3: import android.app.Activity;
   4: import android.content.Intent;
   5: import android.os.Bundle;
   6: import android.view.View;
   7: import android.widget.EditText;
   8:
   9: public class GameScreen1 extends Activity {
  10:
  11:     EditText scoreET;
  12:
  13:     @Override
  14:     public void onCreate(Bundle savedInstanceState) {
  15:         super.onCreate(savedInstanceState);
  16:         setContentView(R.layout.screen1);
  17:         scoreET = (EditText) findViewById(R.id.gameScore);
  18:
  19:     }
  20:
  21:     @Override
  22:     protected void onResume() {
  23:         super.onResume();
  24:         GlobalState state = ((GlobalState) getApplicationContext());
  25:         scoreET.setText(String.valueOf(state.getGameScore()));
  26:     }
  27:
  28:     public void incrementScore(View view) {
  29:         GlobalState state = ((GlobalState) getApplicationContext());
  30:         state.incrementScore();
  31:         scoreET.setText(String.valueOf(state.getGameScore()));
  32:     }
  33:
  34:     public void nextScreen(View view) {
  35:         Intent intent = new Intent(this, GameScreen2.class);
  36:         startActivity(intent);
  37:     }
  38: }

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.

image  image

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 Context which 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).

Wrap Up

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 jwhite@intertech.com.  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.

  • Nik Clayton

    http://www.developerphil.com/dont-store-data-in-the-application-object/ cogently argues that this approach is broken, and will lead to null pointer exceptions.

  • trurl

    @Nik Clayton: The article you linked is only about using this in apps use more than one activity and exchange data.

    He also writes that these null pointer exceptions are true for singletons or other public static fields. Only safe method would to store global data on disk if using several activities that must exchange data.

  • Nick G.

    Worked perfectly. thank you

  • Diego Sebastian Mera

    Jim, are you familiar with RoboGuice? Because if you use it, then using your Application as singleton may not be a good idea, specially if you need other dependencies to inject there (there is no RoboApplication since 2.0). I know that there may some workarounds to inject something on your Application but I personally don’t like them. I usually use a mix between Singleton (a RoboGuice singleton) and SharedPreferences to store a minimum persistent state (for example a auth token & email) to dehydrate my model in case that the app got killed by the OS because of memory issues.

    • Jim White

      Good observation/point Diego. Alternate testing tools could make one or other of the solutions more advantageous.

    • Jim White

      Good observation/point Diego. Alternate testing tools could make one or other of the solutions more advantageous.

  • http://www.dadiehost.com/ Dadie Host

    I had the most aggravating experience in years with SharedPreferences. They didn’t speak good English, talked with very bad accents, talked too fast, did not comprehend what I needed, and worst of all, were stupid. I had had a very very good service person on with me three weeks ago, and he helped me perfectly. I had very high hopes when I called yesterday about one more simple issue, and got these idiots. I now wonder about SharedPreferences customer service ability. I ended up asking someone at work and fixed the problem myself after several minutes of research.

  • Pingback: Android's Application Class | Intertech BlogIntertech Blog - appgong()

{Offer-Title}

{Offer-PageContent}
Click Here