Android Design Patterns: The Singleton Pattern

The Singleton Pattern is a software design pattern that guarantees a class has one instance only and a global point of access to it is provided by that class. Anytime multiple classes or clients request for that class, they get the same instance of the class. This Singleton class may be responsible for instantiating itself, or you can delegate the object creation to a factory class.

Android Design Patterns: The Singleton Pattern

Let’s use the example of a cellphone and its owner. A phone is typically owned by a single person, while a person can own many phones. Anytime one of these phones rings, the same owner picks it up.

Benefits of the Singleton Pattern

In a typical Android app, there are many objects for which we only need one global instance, whether you are using it directly or simply passing it to another class. Examples include caches, OkHttpClientHttpLoggingInterceptorRetrofitGsonSharedPreferences, the repository class, etc. If we were to instantiate more than one of these types of objects, we’d run into problems like incorrect app behaviour, resource overuse, and other confusing results.

Implementation

It’s quite easy to implement this pattern. The following code snippet shows how a Singleton is created.

public class Singleton  {

    private static Singleton INSTANCE = null;

    // other instance variables can be here
    
    private Singleton() {};

    public static Singleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return(INSTANCE);
    }
    
    // other instance methods can follow 
}

In the code above, we have a static variable INSTANCE to hold an instance of the class. We also made the constructor private because we want to enforce noninstantiability—the class can only instantiate itself. The method getInstance() guarantees that the class is instantiated, if it has not been, and that it’s returned to the caller.

Example: Creating a Single Instance of Retrofit

Retrofit is a popular library to connect a REST web service by translating the API into Java interfaces. To learn more about it, check out my tutorial here on ThemeKeeper Tuts+.

  • Android Design Patterns: The Singleton Pattern
    Android SDK
    Sending Data With Retrofit 2 HTTP Client for Android
    Chike Mgbemena

In an Android app, you’ll need a single global instance of a Retrofit object so that other parts of an app such as a UserProfileActivity or SettingsActivity can use it to execute a network request without the need to create an instance every single time we need it. Creating multiple instances would pollute our app with unused retrofit objects, thereby occupying unnecessary memory on an already memory-constrained mobile device.

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
 
public class RetrofitClient {
 
    private static Retrofit retrofit = null;
 
    public static Retrofit getClient(String baseUrl) {
        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

So anytime client A calls RetrofitClient.getClient(), it creates the instance if it has not been created already, and then when client B calls this method, it checks if the Retrofit instance already exists. If so, it returns the instance to client B instead of creating a new one.

Dealing With Multithreading

In the Android system, you can spin off multiple threads to perform different tasks. These threads can end up executing the same code block simultaneously. In the case of the Singleton class above, this could lead to the creation of multiple object instances, which violates the contract of a Singleton. So our Singleton code snippet method getInstance() is not thread safe. We’ll now look at ways to make it thread safe.

Synchronize the getInstance() Method

One of the ways to make the singleton code thread safe is by making the method getInstance() a synchronized one. Doing this only allows one thread to run the method at a time, forcing every other thread to be in a wait or blocked state.

public class Singleton  {

    private static Singleton INSTANCE = null;

    // other instance variables can be here
    
    private Singleton() {};

    public static synchronized Singleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return(INSTANCE);
    }
    
    // other instance methods can follow 
}

This approach makes our code thread safe, but it is an expensive operation. In other words, this can slow down performance. So you have to investigate and see if the performance cost is worthwhile in your application.

Eagerly Create an Instance

Another approach to deal with multiple threads accessing the singleton is to create the Singleton instance immediately when the class is loaded or initialized (by the Android ClassLoader in the Dalvik VM). This makes the code thread safe. Then the object instance will already be available before any thread accesses the INSTANCE variable.

public class Singleton  {

    private static Singleton INSTANCE = new Singleton();

    // other instance variables can be here
    
    private Singleton() {};

    public static Singleton getInstance() {
       return(INSTANCE);
    }
    
    // other instance methods can follow 
}

A drawback to this approach is that you can end up creating an object that might never be used, thereby occupying unnecessary memory. So this approach should typically only be used if you are sure that the singleton will be accessed.

Bonus: Using Dagger 2

A dependency injection library such as Dagger can help you wire up your object dependencies and create singletons by using the @Singleton annotation. This will ensure that the object is only initialized once throughout the application lifecycle.

@Module
public class NetworkModule {

    @Provides
    @Singleton
    public Gson gson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        return gsonBuilder.create();
    }

    @Provides
    @Singleton
    public HttpLoggingInterceptor loggingInterceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(
                message -> Timber.i(message));
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return interceptor;
    }

    @Provides
    @Singleton
    public Cache cache(File cacheFile) {
        return new Cache(cacheFile, 10 * 1000 * 1000); //10MB Cache
    }

    @Provides
    @Singleton
    public File cacheFile(@ApplicationContext Context context) {
        return new File(context.getCacheDir(), "okhttp_cache");
    }

    @Provides
    @Singleton
    public OkHttpClient okHttpClient(HttpLoggingInterceptor loggingInterceptor, Cache cache) {
        return new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .cache(cache)
                .build();
    }

    @Provides
    @Singleton
    public Retrofit retrofit(OkHttpClient okHttpClient, Gson gson) {
        return new Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(okHttpClient)
                .baseUrl("you/base/url")
                .build();
    }
}

In the code above, we create a single instance of GsonCache, FileOkHttpClient and finally Retrofit types to be provided from the dependency graph generated by Dagger.

To learn more about Dagger 2, check out our tutorial here on ThemeKeeper Tuts+.

  • Android Design Patterns: The Singleton Pattern
    Android SDK
    Dependency Injection With Dagger 2 on Android
    Kerry Perez Huanca

Conclusion

In this short tutorial, you learned about the Singleton pattern in Android: what it is, the benefits of using it, how to implement it by writing your own, and some ways of dealing with multiple threads. I also showed you how to use a third-party library such as Dagger 2.

In the meantime, check out some of our other courses and tutorials on the Java language and Android app development!

  • Android Design Patterns: The Singleton Pattern
    Android SDK
    RxJava 2 for Android Apps: RxBinding and RxLifecycle
    Jessica Thornsby
  • Android Design Patterns: The Singleton Pattern
    Android SDK
    Practical Concurrency on Android With HaMeR
    Tin Megali
  • Android Design Patterns: The Singleton Pattern
    Android
    Ensure High-Quality Android Code With Static Analysis Tools
    Chike Mgbemena
  • Android Design Patterns: The Singleton Pattern
    Android SDK
    Create an Intelligent App With Google Cloud Speech and Natural Language APIs
    Ashraff Hathibelagal