Why you should use Singleton Pattern in your Android Application?
Let me tell you why i started using Singleton pattern in my code.
So all this goes back to my learning of MVP pattern in android. For the sake of completeness, let’s talk a bit about MVP pattern. So MVP or Model-View-Presenter pattern is a way of separating various workflows into separate layers. Model provides data, View controls the widgets or UI, Presenter acts as intermediary between View and Model controlling the interconnection and handling the logic between two.
Here the Model is AppDataManager class, responsible for loading the data from various sources like sql database, network calls, shared prefs etc.
Now let’s assume that you aren’t aware of Singleton type of thing. So every time, whenever you want to load data, you will create a new instance of AppDataManager class and subsequently call its method for loading the required data/list.
new AppDataManager().yourMethod();
Weird things may not be visible for a small project, but as your project grows, you will start putting unnecessary burden on the system memory, or in other words, you are blacklisting your app on memory usage/management.
Let’s understand this with an example. You have an approx 20 methods in your app to load data and everytime, you create an instance of AppDataManager and call its required loading method. You will then end up on having 20 objects of AppDataManager class in the memory, each of which is just a clone of other. Now the obvious question arises,
Why to keep 20 similar things if they all are identical?
Here comes Singleton Pattern in picture, which is nothing special but it is just to control the number of instances of a particular class to ‘one’ or in other words, using the same object throughout the app.
Sounds better na?
You could now say, okay, why not use the same object everywhere by creating it in Application class and declaring it as static field. This will now act as a global variable which is available everywhere and anytime when needed. Hence you do something like this:
public class ApplicationClass extends Application {
private static AppDataManager appDataManager;
@Override
public void onCreate() {
super.onCreate();
appDataManager = new AppDataManager();
}
}
Great! You are going in right direction. But this solution lacks recommended code pattern and standards. This solution works if and only if you are the lone developer of your app. Things starts ruining when you are involved in a team. Suppose another developer joins, he then makes another instance of AppDataManager somewhere(by mistake) and used that to load data. Ofcourse you can ask not to do this and use the static field in Application class instead. But why not choose a standard code pattern, so that a new instance can’t be created anywhere.
In Singleton pattern, we prevent multiple instances of a class by checking the instance for its existence before creating a new instance. If our object doesn’t exist (or is null) we create a new instance. So in our AppDataManger class we do something like this:
public class AppDataManager { private static AppDataManager uniqueInstance;
...
private AppDataManager(Context context) {
...
}
public static AppDataManager getInstance() {
if (uniqueInstance == null)
throw new NullPointerException("Please call initialize() before getting the instance.");
return uniqueInstance;
}
public synchronized static void initialize(Context applicationContext) {
if (applicationContext == null)
throw new NullPointerException("Provided application context is null");
else if (uniqueInstance == null) {
uniqueInstance = new AppDataManager(applicationContext);
}
}
...
}
And in our Application class we call the initialize method:
public class ApplicationClass extends Application {
...
@Override
public void onCreate() {
super.onCreate();
AppDataManager.initialize(getApplicationContext());
}
}
Now let’s understand this in detail:
First we call initialize() in AppDataManager class which takes application context as param. In this method, we first check for null value of context and after the successful check we then create a unique instance of AppDataManager class if it doesn't exist. Note that we make this method static (because we can’t call a non static method of a class without creating its object) and synchronized (in order to prevent multithreading or running this method twice at the same time which leads to two instances).
Also note that the constructor is private so you can’t create an object of this class outside it. Also to prevent Java Reflection Api we could add this to the constructor:
private AppDataManager(Context context) {
//Prevent from the reflection api.
if (uniqueInstance != null)
throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
...
}
Then to access the unique object or uniqueInstance we call getInstance() method. Note that this is also static method, so again you don’t need to create an object of AppDataManger class if you want to use it in future. This method also checks whether you called initialize() of AppDataManager or not. Hence whenever anywhere needed, call it like this:
AppDataManager.getInstance().yourMethod(); //yourMethod is a non- static method
Now go back to the top and compare the two approaches. You can yourself see which is better in both functioning and styling.
Whola! Both you and I learnt something new today. Congrats!
Here are the links to the two classes mentioned above:
ApplicationClass: https://github.com/apgapg/pixstory-android/blob/master/app/src/main/java/com/jullae/ApplicationClass.java
AppDataManager: https://github.com/apgapg/pixstory-android/blob/master/app/src/main/java/com/jullae/data/AppDataManager.java
Furthur Reading on Singleton:
https://android.jlelse.eu/how-to-make-the-perfect-singleton-de6b951dfdb0
Thank You for giving a read to this.