单例 大家很熟悉了 Java里有double check的写法 还有就是静态内部类的写法,在kotlin中有这样几种写法分别为不带参数 和带参数的写法 一共4种
参考: https://medium.com/@BladeCoder/kotlin-singletons-with-argument-194ef06edd9e
一,不带参数的单例
object Singleton {
init{ //here init your data}
fun test(){ }
}
//搞定 就是这么简单 使用的时候 Singleton.INSTANCE.test() , INSTANCE我们没有定义啊 不要慌张它是自动生成的
二,带参数的单例 A reusable Kotlin implementation
1,实现一个通用的InstanceHolder类 SingletonHolderKt 可以复用的实现方式
2,自己的单例类 参考: https://medium.com/@BladeCoder/kotlin-singletons-with-argument-194ef06edd9e
class Manager private constructor(context: Context) {
init {
// Init using context argument
}
fun invokeSingletonMethod(){ do something }//我们自己定义的方法
companion object : SingletonHolder(::Manager) //::Manager这个直接调用的是manager的构造方法
}
调用的时候:Manager.getInstance(your appContext).invokeSingletonMethod();
:: 这个符号在kotlin中意思有2个 1是 Class References 类引用 2是方法引用
下边是stackOverflow上的解释
Class References: The most basic reflection feature is getting the runtime reference to a Kotlin class. To obtain the reference to a statically known Kotlin class, you can use the class literal syntax:
val c = MyClass::class//The reference is a value of type KClass.
Note that a Kotlin class reference is not the same as a Java class reference. To obtain a Java class reference, use the .java property on a KClass instance.
It’s also the syntax for method references as in this simple example:
list.forEach(::println)
It refers to println defined in Kotlin Standard library.
kotlin这么实现的单例 看着代码并不简单也不优雅 但是 这段代码是直接从kotlin源码中lazy()方法里抠出来的 下边是老外的一段解释
This may not be the most compact or elegant Kotlin code, but it’s the one producing the most efficient bytecode for the double-checked locking algorithm. Trust the Kotlin authors on this: this code is actually borrowed directly from the implementation of the lazy() function in the Kotlin standard library, which is synchronized by default. It has been modified to allow passing an argument to the creator function.
Given its relative complexity, it’s not the kind of code you want to write (or read) more than once, so the goal is to reuse that SingletonHolder class everytime you have to implement a singleton with argument.
中心思想就是我们在创建自己的带参数的单例模式时复用SingletonHolder 这个就可以了
3,还有使用建造者模式实现的 下边是android jetpack架构组件中room 数据库单例的实现方式
You can also use this idiom when a singleton implementation is generated by an external library and the builder requires an argument. Here’s an example using the Room Persistence Library for Android:
@Database(entities =arrayOf(User::class), version = 1)
abstract class UsersDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object : SingletonHolder({
Room.databaseBuilder(it.applicationContext,
UsersDatabase::class.java,"Sample.db")
.build()
})
}
如果是没有参数的话可以直接使用lazy
Note: When the builder doesn’t require an argument, you can simply use a lazy delegated property instead:
interface GitHubService {
companion object {
val instance: GitHubServiceby lazy {
val
retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build()
retrofit.create(GitHubService::class.java)
}
}
}