Get into the habit of writing together! This is the third day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .
1. Three ways of singleton implementation
object
Look at the code first:
object Pro {
}
复制代码
It is so simple to realize the singleton of Pro. We can decompile it into java code to see the specific implementation principle:
public final class Pro {
@NotNull
public static final Pro INSTANCE;
private Pro() {
}
static {
Pro var0 = new Pro();
INSTANCE = var0;
}
}
复制代码
First of all Pro
, the constructor of the class is declared as private
, and secondly, you can see that this is a singleton implemented by a static code block. Using the feature that the static code block of the class will only be executed once, it belongs 线程安全且饿汉式
to;
In java, Pro.INSTANCE
this singleton is obtained, while kotlin directly Pro
obtains the singleton
lazy
Code first:
class Pro private constructor() {
companion object {
val INSTANCE by lazy {
Pro()
}
}
}
复制代码
It mainly uses the properties declared by the companion object as static variables, and the default implementation mode of lazy is lock thread-safe. This is a 线程安全且懒汉式
singleton implementation. For lazy
more information, please refer to one of the Kotlin development practices.
- double check lock
Above code:
@Volatile
var singleton: Pro? = null
fun getInstance(): Pro {
if (singleton == null) {
synchronized(Pro::class.java) {
if (singleton == null) {
singleton = Pro()
}
}
}
return singleton!!
}
复制代码
The above is the kotlin implementation of java double-checked lock, where:
@Volatile
Guarantee the order of code instructionsgetInstance
The inner and outer layers of the method aresingleton
empty to ensuresingleton
that the initialization has been completed, and the threads do not need to compete for locks.getInstance
The inner layer of the method issingleton
empty to ensure that if the previous thread has been initializedsingleton
, subsequent threads should not be initialized again.
As you can see, this is a 线程安全且懒汉式
singleton implemented in a way
2. typealias
Take an alias for a complex type
This typealias
keyword is mainly used to give an alias to the type. The following two usage scenarios are described below:
- function type alias
In daily development, function types should be commonly used, such as
//拼接Int和String类型并返回String类型
val block: ((Int, String) -> String)? = null
复制代码
This function type (Int, String) -> String)
is cumbersome to write and poorly readable, and now it typealias
's time to upload:
typealias Concat = (Int, String) -> String
val block: Concat? = null
复制代码
(Int, String) -> String)
It is not Concat
only convenient to use, but also easy to see the usage scenario of this function type: splicing
- Simplified generic pass
When using ViewModel
, we may often encapsulate the return of the interface as follows:
class MainViewModel: ViewModel() {
val data: MutableLiveData<Response<String>> = MutableLiveData()
fun test() {
data.value = Response("haha")
}
data class Response<T>(val data: T? = null)
}
复制代码
Used Response
to encapsulate the server return, the generic type T
represents the entity class into which the response data can be deserialized.
As you can see above, each definition MutableLiveData
has to be declared in its generic type Response<T>
, because ours Response
is a unified encapsulation of all interface responses, and it is a definite type, and the type in it Response<T>
is the type that needs to be dynamically specified T
each time it is created .MutableLiveData
Can you omit it? Now it's time to Response<T>
upload :Response
typealias
typealias ExternalLiveData<T> = MutableLiveData<MainViewModel.Response<T>>
复制代码
So every time you create MutableLiveData
it, you can write it like this:
val data1: ExternalLiveData<String> = MutableLiveData()
复制代码