4

Android documentation for Application states: There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality [i.e. maintain global application state] 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.

My request is: Can you explain, and provide code sample that implements the above suggestion for maintaining global state.

Note that there is already a suggestion that recommends subclassing Application: How to declare global variables in Android?

Thank you.

Community
  • 1
  • 1
HalukO
  • 333
  • 1
  • 4
  • 10

2 Answers2

7

Correction to StinePike's answer regarding context in the ApplicationState. In the code posted the context passed in to the application state is held on to. If the context passed in is an activity or similar unit then the activity would be leaked and prevented from being garbage collected.

The android documentation for the Application class states you should "internally use Context.getApplicationContext() when first constructing the singleton."

public class ApplicationState {
    private Context applicationContext;
    private static ApplicationState instance;

    private ApplicationState(Context context) {
        this.applicationContext = context.getApplicationContext();
    }

    public static ApplicationState getInstance(Context context) {
        if(instance == null) {
            instance = new ApplicationState(context);
        }
        return instance;
    }
}
Ryan Thomas
  • 479
  • 5
  • 16
  • Could you please give a brief explanation of what they said in the API doc for `Context.getApplicationContext()`: "If used from the Context returned here, the receiver is being registered with the global state associated with your application. Thus it will never be unregistered for you. This is necessary if the receiver is associated with static data, not a particular component. However using the ApplicationContext elsewhere can easily lead to serious leaks if you forget to unregister, unbind, etc." – Antonio Sesto Mar 06 '15 at 08:15
  • 1
    @AntonioSesto The API doc is referring to two situations. In the first situation it is referring to using a context object such as an activity directly to register a receiver such as `activity.registerReceiver(...)` and pointing out that the receiver is expected to be unregistered before the activity is done being destroyed. It also points out that if you fail to unregister the receiver the framework will do so AUTOMATICALLY and thus prevent the registered receiver and references from leaking. – Ryan Thomas Apr 13 '15 at 13:50
  • 1
    @AntonioSesto In the second situation, the one you quotes the API doc is referring to using the application context such as `activity.getApplicationContext().registerReceiver(...)` in which case you will have access to the static data in the application's "global state" but the registered receiver will not be automatically cleaned up at any point meaning it is up to the developer to make sure they do not accidentally create a situation in which the registered receiver or similar objects are allowed to create leaks. – Ryan Thomas Apr 13 '15 at 13:50
6

If I am not wrong your are trying to save global variables without extending Application. If so you can do two things

if you don't need any context then you ca simply use a class with static members like this

public class ApplicationState {
    public static boolean get() {
        return b;
    }

    public static void set(boolean a) {
        b = a;
    }

    private static boolean b;
}

And if you need a context but you don't want to extend Application you can use

Public class ApplicationState {
    private Context context;
    private static ApplicationState instance;

    private ApplicationState(Context context) {
        this.context = context;


    public static ApplicationState getInstance(Context context) {
        if (instance == null) {
            instance = new ApplicationState(context);
        }
        return instance;
    }

    public void someMethod(){}
}

So you can call some method like this ApplicationState.getInstance(context).somemethod();

stinepike
  • 54,068
  • 14
  • 92
  • 112
  • As Ryan Thomas pointed out it is correct to use Context.getApplicationContext() instead of passed context. – Octavian Nov 10 '14 at 08:36
  • As a safer side for suggestion 1: you can mark it as a private constructor, so no can instantiate this. – Punith Raj Jun 23 '15 at 12:01