Android extending Application pattern doubts

153 views Asked by At

I have extended my Application in my Android App in order to store the different typefaces I use within my application. Everything is working fine, however I am not understanding the singleton part of the code and what is the goal of the getInstance (I set a breakpoint there and it is never called, also if I change the name of the method the Application works fine as well). Could someone enlighten me about this pattern? I don't normally work with OOP so it might be a stupid question.

MyApplication.java

    public class MyApplication extends Application {
    private Typeface _typefaceNormal;
    private Typeface _typefaceBold;

    private static MyApplication singleton;

    public MyApplication getInstance() {
        return singleton;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        singleton = this;
        this._typefaceNormal = Typeface.createFromAsset(getAssets(),"PTS55F.TTF");
        this._typefaceBold = Typeface.createFromAsset(getAssets(), "PTS75F.TTF");
    }

    public Typeface getNormalFont() {
        return this._typefaceNormal;
        // return this._typefaceNormal;
    }

    public Typeface getBoldFont() {
        return this._typefaceBold;
        // return this._typefaceBold;
    }
}

And then I make the call like this:

this._typeface = ((MyApplication) _activity.getApplicationContext()).getNormalFont();

EDIT

From the answers I gathered, and some additional research, this was the class I ended up using:

    public class MyGlobalConfig {
    private static MyGlobalConfig singleton;
    private Typeface _typefaceNormal;
    private Typeface _typefaceBold;

    private MyGlobalConfig() {

    }

    public static MyGlobalConfig getInstance() {
        if (singleton == null) {
            singleton = new MyGlobalConfig();
        }
        return singleton;
    }

    public void init(Context ctx, String typefaceNormal, String typefaceBold) {
        this._typefaceNormal = Typeface.createFromAsset(ctx.getAssets(),
                typefaceNormal);
        this._typefaceBold = Typeface.createFromAsset(ctx.getAssets(),
                typefaceBold);
    }

    public Typeface getNormalFont() {
        return this._typefaceNormal;
        // return this._typefaceNormal;
    }

    public Typeface getBoldFont() {
        return this._typefaceBold;
        // return this._typefaceBold;
    }
}

I initialize it as:

MyGlobalConfig.getInstance().init(getApplicationContext(), normalFont, boldFont);

And set my Fonts as:

MyGlobalConfig.getInstance().getNormalFont();
2

There are 2 answers

1
Eric Levine On BEST ANSWER

The purpose of the singleton pattern is to enforce that only one instance of a class can be created. You don't really achieve that here though. The proper way to do it in Java is to make the constructor private and then set the static variable to the singleton instance of the class. For example:

public class MySingletonClass{
  private static MySingletonClass singleton;

  // private constructor
  private MySingletonClass(){}

  public static MySingletonClass getInstance(){
   if(singleton == null){
     singleton = new MySingletonClass();
   }
   return singleton;
  }
}

When it comes to working with Android, there is no need to make your Application class a singleton. Android will only create one instance of it and manage it for you. Also, since the Application class already has a public constructor defined, I don't believe that the compiler will allow you to make the constructor private in your extended class, so you couldn't enforce the singleton pattern.

0
Robert Estivill On

That's because you are not using the static method MyApplication.getInstance(). Instead, your are accessing the reference through the context.getApplicationContext() which in this case results in the same reference than the "singleton" static variable.

Accessing the instance through the static method getInstance() gives you the ability to access it without having a context reference, and saving you from casting ((MyApplication) _activity.getApplicationContext()). On the bad side, it couples your code and makes it less testeable.