Práctica de desarrollo de proyectos de Kotlin 2

¡Acostúmbrate a escribir juntos! Este es el tercer día de mi participación en el "Nuggets Daily New Plan · April Update Challenge", haz clic para ver los detalles del evento .

1. Tres formas de implementación singleton

  • object

Mira el código primero:

object Pro {
}
复制代码

Es tan simple realizar el singleton de Pro. Podemos descompilarlo en código Java para ver el principio de implementación específico:

public final class Pro {
   @NotNull
   public static final Pro INSTANCE;

   private Pro() {
   }

   static {
      Pro var0 = new Pro();
      INSTANCE = var0;
   }
}
复制代码

En primer lugar Pro, el constructor de la clase se declara como private, en segundo lugar, puede ver que se trata de un singleton implementado por un bloque de código estático.Usando la característica de que el bloque de código estático de la clase solo se ejecutará una vez, pertenece 线程安全且饿汉式a ;

En java Pro.INSTANCEse obtiene este singleton, mientras que kotlin Proobtiene directamente el singleton

  • lazy

Código primero:

class Pro private constructor() {
    companion object {
        val INSTANCE by lazy {
            Pro()
        }
    }
}
复制代码

Utiliza principalmente las propiedades declaradas por el objeto complementario como variables estáticas, y el modo de implementación predeterminado de lazy es lock thread-safe. Esta es una 线程安全且懒汉式implementación singleton. Para lazyobtener más información, consulte una de las prácticas de desarrollo de Kotlin.

  • bloqueo de doble verificación

Código anterior:

@Volatile
var singleton: Pro? = null

fun getInstance(): Pro {
    if (singleton == null) {
        synchronized(Pro::class.java) {
            if (singleton == null) {
                singleton = Pro()
            }
        }
    }
    return singleton!!
}
复制代码

Lo anterior es la implementación de kotlin del bloqueo de verificación doble de Java, donde:

  1. @VolatileGarantizar el orden de las instrucciones del código.
  2. getInstanceLas capas interna y externa del método están singletonvacías para garantizar singletonque la inicialización se haya completado y que los subprocesos no necesiten competir por los bloqueos.
  3. getInstanceLa capa interna del método está singletonvacía para garantizar que si el subproceso anterior se ha inicializado singleton, los subprocesos posteriores no deben inicializarse nuevamente.

Como puede ver, este es un 线程安全且懒汉式singleton implementado de una manera

2. typealiasToma un alias para un tipo complejo

Esta typealiaspalabra clave se utiliza principalmente para dar un alias al tipo. A continuación se describen los dos escenarios de uso siguientes:

  • alias de tipo de función

En el desarrollo diario, los tipos de función deben usarse comúnmente, como

//拼接Int和String类型并返回String类型
val block: ((Int, String) -> String)? = null
复制代码

Este tipo de función (Int, String) -> String)es engorroso de escribir y poco legible, y ahora es typealiasel momento de cargar:

typealias Concat = (Int, String) -> String
val block: Concat? = null
复制代码

No solo (Int, String) -> String)es Concatconveniente de usar, sino que también es fácil ver el escenario de uso de este tipo de función: empalme

  • Pase genérico simplificado

Cuando usamos ViewModel, a menudo podemos encapsular el retorno de la interfaz de la siguiente manera:

class MainViewModel: ViewModel() {
    val data: MutableLiveData<Response<String>> = MutableLiveData()
    
    fun test() {
        data.value = Response("haha")
    }
    
    data class Response<T>(val data: T? = null)
}
复制代码

Utilizado Responsepara encapsular la devolución del servidor, el tipo genérico Trepresenta la clase de entidad en la que se pueden deserializar los datos de respuesta.

Como puede ver arriba, cada definición MutableLiveDatadebe declararse en su tipo genérico Response<T>, porque la nuestra Responsees una encapsulación unificada de todas las respuestas de la interfaz, y es un tipo definido, y el tipo que contiene Response<T>es el tipo que debe especificarse dinámicamente Tcada momento en que se crea .MutableLiveData

¿Puedes omitirlo? Ahora es el momento de Response<T>subir :Responsetypealias

typealias ExternalLiveData<T> = MutableLiveData<MainViewModel.Response<T>>
复制代码

Entonces, cada vez que lo cree MutableLiveData, puede escribirlo así:

val data1: ExternalLiveData<String> = MutableLiveData()
复制代码

Supongo que te gusta

Origin juejin.im/post/7082560219615592456
Recomendado
Clasificación