Skip to main content

Command Palette

Search for a command to run...

How to Create Singleton Class in Kotlin?

Singleton is a global object that can be accessed from everywhere in your application. This article shows different ways of creating it in Kotlin.

Updated
2 min read
How to Create Singleton Class in Kotlin?
V

I'm a self-taught hobbyist Android developer who loves to build projects and share valuable tips for new Android developers.

Feel free to comment, share or connect with me!

In Kotlin, you can use the object declaration to implement singleton. However, if you don't aware of this object keyword, you probably will do something like this.

Conventional Singleton

class Singleton private constructor() {

    companion object {
        @Volatile
        private lateinit var instance: Singleton

        fun getInstance(): Singleton {
            synchronized(this) {
                if (!::instance.isInitialized) {
                    instance = Singleton()
                }
                return instance
            }
        }
    }

    fun show() {
        println("This is Singleton class!")
    }
}

fun run() {
    Singleton.getInstance().show()
}
  • private constructor() is used so that this can't be created as usual class
  • @Volatile and synchronized() are used to make sure this Singleton creation is thread-safe.

Object Declaration Singleton

This can be simplified to

object Singleton {
    fun show() {
        println("This is Singleton class!")
    }
}

fun run() {
    Singleton.show()
}

Singleton is a class and also a singleton instance where you can access the singleton object directly from your code.

Constructor Argument Singleton

The limitation of this object declaration is you can't pass a constructor parameter to it to create the singleton object. If you want to do that, you still need to use back the first conventional method above.

class Singleton private constructor(private val name: String) {

    companion object {
        @Volatile
        private lateinit var instance: Singleton

        fun getInstance(name: String): Singleton {
            synchronized(this) {
                if (!::instance.isInitialized) {
                    instance = Singleton(name)
                }
                return instance
            }
        }
    }

    fun show() {
        println("This is Singleton $name class!")
    }
}

fun run() {
    Singleton.getInstance("liang moi").show()
}

Conclusion

I personally use singleton for simple utility class (use object declaration) and database (use convention singleton method - because it is required to pass in argument).

M

Great writing, Vincent.

I have 0 knowledge in Kotlin, as I speak in Java, Python and a little Javascript, but I like to extend my view, so I deciced to learn a little bit about Kotlin and read your article. 😊

I have one question too. I have seen many singletons during my life, but I have never seen one which has a constructor, except when using dependency injection.

I see one problem with it. If you really call the instance method from multiple places and pass different parameters (name), then I would expect to get a singleton with the name I specified, but in reality I will get a singleton with a name which was specified in the first call of the instance method.

Am I missing something? Is this common in Kotlin to give parameters to singletons?

1
V

Thanks, Miki, for your comment. I think your understanding is correct. It will always return the first created instance.

Technically, I think the code should throw an exception if the requested singleton name (parameter) is different from the first originally created.

The example is to demonstrate sometimes we can't just use object keyword, especially you need an additional parameter. Maybe this example is not a good one. :)

Whether it is common or not to give parameters to singleton, I'm not sure, but database creation is pretty common to be used as singleton. See below example. It doesn't have a constructor parameter (although it can). But, it requires passing in context to create database.

abstract class ArticlesDatabase : RoomDatabase() {

    protected abstract val dao: ArticlesDao

    companion object {
        @Volatile
        private lateinit var instance: ArticlesDatabase

        fun getInstance(context: Context): ArticlesDatabase 
        {
            synchronized(this) {
                if (!::instance.isInitialized) {
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        ArticlesDatabase::class.java,
                        "articles.db")
                        .fallbackToDestructiveMigration()
                        .build()
                }

                return instance
            }
        }
    }
}
11
M

Thanks for the explanation, Vincent Tsen. 😊

1