單例 大家很熟悉了 Java里有double check的寫法 還有就是靜態(tài)內(nèi)部類的寫法纵装,在kotlin中有這樣幾種寫法分別為不帶參數(shù) 和帶參數(shù)的寫法 一共4種
參考:?https://medium.com/@BladeCoder/kotlin-singletons-with-argument-194ef06edd9e
一,不帶參數(shù)的單例
object Singleton {
? ? ?init{ //here init your data}
? ? ?fun test(){? }
}??
//搞定 就是這么簡單 使用的時(shí)候?Singleton.INSTANCE.test()? ,?INSTANCE我們沒有定義啊 不要慌張它是自動(dòng)生成的
二,帶參數(shù)的單例? ?A reusable Kotlin implementation?
1评姨,實(shí)現(xiàn)一個(gè)通用的InstanceHolder類?SingletonHolderKt? 可以復(fù)用的實(shí)現(xiàn)方式
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這個(gè)直接調(diào)用的是manager的構(gòu)造方法
}
調(diào)用的時(shí)候:Manager.getInstance(your appContext).invokeSingletonMethod();
:: 這個(gè)符號(hào)在kotlin中意思有2個(gè)? 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這么實(shí)現(xiàn)的單例 看著代碼并不簡單也不優(yōu)雅 但是 這段代碼是直接從kotlin源碼中l(wèi)azy()方法里摳出來的 下邊是老外的一段解釋
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.
中心思想就是我們?cè)趧?chuàng)建自己的帶參數(shù)的單例模式時(shí)復(fù)用SingletonHolder 這個(gè)就可以了?
3,還有使用建造者模式實(shí)現(xiàn)的? 下邊是android jetpack架構(gòu)組件中room 數(shù)據(jù)庫單例的實(shí)現(xiàn)方式
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()
})
}
如果是沒有參數(shù)的話可以直接使用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)
}
}
}