1. Hungry Chinese singleton
Kotlin supports singletons at the grammatical level, that is, the object keyword, which is much simpler than the template code of Java singletons:
object WorkSingleton
After decompilation, you will find that object
it is actually a 一个
static-based singleton of the hungry man, which is somewhat thread-safe. The disadvantage is that lazy loading cannot be achieved:
public final class WorkSingleton {
public static final WorkSingleton INSTANCE;
static {
WorkSingleton var0 = new WorkSingleton();
INSTANCE = var0;
}
}
2. Lazy singleton
And the use of associated objects by lazy
may also be implemented a single embodiment, may be implemented lazy thread safe Singleton formula
class WorkSingleton private constructor() {
companion object {
//LazyThreadSafetyMode.SYNCHRONIZED可以省略
val INSTANCE1 by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
WorkSingleton() }
}
}
In a non-multithreaded environment, yes mode = LazyThreadSafetyMode.NONE
, it is a thread-safe singleton to improve performance
3. Singleton with parameters
Sometimes you want to pass parameters when the singleton is initialized, for example
Singleton.getInstance(context).doSome()
It can be achieved through the inheritance of companion objects:
class WorkSingleton private constructor(context: Context) {
init {
// Init using context argument
}
companion object : SingletonHolder<WorkSingleton, Context>(::WorkSingleton)
}
open class SingletonHolder<out T : Any, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile
private var instance: T? = null
fun getInstance(arg: A): T {
val i = instance
if (i != null) {
return i
}
return synchronized(this) {
val i2 = instance
if (i2 != null) {
i2
} else {
val created = creator!!(arg)
instance = created
creator = null
created
}
}
}
}
It is very similar to the double check lock mechanism in Java. SingletonHolder
If the class has been initialized, it will return directly. If it has not been initialized, enter the synchronized code block to create an object.
Through Kotlin, the companion object as a subclass realizes the function equivalent to static inheritance. Therefore, we use SingletonHolder as the base class of the singleton companion object to facilitate reuse on the singleton class. For the singleton mode that needs to pass parameters, only You need to inherit the companion object of the singleton class SingletonHolder
, and then specify the singleton class and parameter types through generics:
class FileSingleton private constructor(path: String) {
companion object : SingletonHolder<FileSingleton, String>(::FileSingleton)
}