Kotlin 学习

  • Post author:
  • Post category:其他





类与对象



构造函数

  • 在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。



主构造函数

  • 主构造函数是类头的一部分
  • 主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。



次构造函数



init代码块

这里init代码块是作为主构造函数的一部分。

最好不要在这里调用类里定义的具有一定业务职责的init()函数。

eg.

class Constructors {
    constructor(i: Int) {
        println("Constructor")
    }

	//error: firstProperty not init,but used in init()
	//java.lang.NullPointerException: Parameter specified as non-null is null
    init {
        init()
    }
    val firstProperty = "First property: ".also(::println)
    
	fun init(){
		println("use firstProperty: $firstProperty ")
	}
}



初始化顺序

主构造函数(init块、属性初始化器 按先后顺序) — 次级构造函数

初始化顺序




作用域

todo




协程



引例

参考:

Kotlin Coroutine协程

场景:

一个网络/耗时操作,需要异步执行,通过回调返回结果。

api.getUserInfo(userId,callback);

java:

开启异步线程,等待回调,处理结果。

场景:

三个网络/耗时操作,需要异步执行,通过回调返回结果。

后续操作需要等待这三个结果都返回后,再处理。比如一起给UI显示。

api.getUserInfo(userId,callback);
api.getOnlineStatus(userId,callback);
api.getLevelInfo(userId,callback);

java:

1.并行转串行,回调嵌套处理

2.使用类似CompletableFuture的框架

kotlin:

GlobalScope.launch {
  //async里的3个block是同时请求,无需等待前一个的结果
  val userInfo = async { api.getUserInfo(userId) }
  val onlineStatus = async { api.getOnlineStatus(userId) }
  val levelInfo = async { api.getLevelInfo(userId) }
  //等待3个请求全部返回了,再组装数据
  val composeInfo = compose(userInfo.await(), onlineStatus.await(), levelInfo.await())
  getLiveData().postValue(composeInfo)//刷新UI
}



是什么


扔物线-协程


协程就是个线程框架。

在 Kotlin 里,协程就是基于线程来实现的一种更上层的工具 API,类似于 Java 自带的 Executor

系列 API 或者 Android 的 Handler 系列 API。

协程提供了方便的API,在设计思想上是一个基于线程的上层框架,理解为新造了一些概念用来帮助你更好地使用这些 API。



怎么用

三个启动协程的api



runBlocking

阻塞当前线程的运行

具体阻塞非阻塞的区别具体看:


Kotlin 协程中,关于 runBlocking, launch ,withContext ,async,doAsync 之间的简单区别

runBlocking {
    getImage(imageId)
}



launch

创建协程

//可以使用GlobalScope或者自己创建CoroutineScope
val job coroutineScope.launch {getImage(imageId)}
job.cancel()
job.join()  //挂起当前的协程直到 Job 的状态变为isCompleted



async

相比lanch可以获得一个返回值,

val deferred = coroutineScope.async { getImage(imageId) }
deferred.await() 
//Deferred 继承自 Job 接口,但是扩展了几个函数,用于获取 async 函数的返回值。



withContext

suspend函数,不创建新的协程,指定闭包内的逻辑运行在哪个线程。

会挂起当前协程,切换到指定的线程,执行闭包内的逻辑,执行完之后,自动把线程切回去继续执行原来协程的代码。多个withContext的执行顺序由外层的协程顺序控制。

闭包最后一行为withContext块的返回值

CoroutineScope(Dispatchers.Main).launch {
	val task1 = withContext(Dispatchers.IO) {
		delay(2000)
		Log.e("TAG", "1.执行task1.... [当前线程为:${Thread.currentThread().name}]")
		"one"  //返回结果赋值给task1
	}
}



概念

非阻塞挂起

结构化并发

参考


Kotlin中的协程 – 基本使用



参考文章


Kotlin 协程的挂起好神奇好难懂?今天我把它的皮给扒了



理解 Kotlin 的 suspend 函数



ktolin-proposal




设计模式



单例模式

//todo



Builder模式



code

data class Person(
    val name:String,
    val family:String,
    val age:Int,
    val nationalCode: String?,
    val email: String?,
    val phoneNumber: String?
) {

    // Private constructor
    private constructor(builder: Builder) : this (
        builder.name,
        builder.family,
        builder.age,
        builder.nationalCode,
        builder.email,
        builder.phoneNumber
    )

    // Builder class

    // 1 Necessary parameters in Builder class : name , family
    class Builder(val name :String,val family :String) {

        // 2 Optional parameters in Builder class :
        var age: Int = 0
            private set
        var nationalCode: String? = null
            private set
        var email: String? = null
            private set
        var phoneNumber: String? = null
            private set

        fun age(age: Int) = apply { this.age = age }
        fun nationalCode(nationalCode: String) =
            apply { this.nationalCode = nationalCode }
        fun email(email: String) = apply { this.email = email }
        fun phoneNumber(phoneNumber: String) =
            apply { this.phoneNumber = phoneNumber }

        // 3 Create
        fun create() = Person(this)

    }
}



use

val firstPerson = Person.Builder(
    name = "Adnan",
    family = "Abdollah Zaki")
    .age(32)
    .email("Adnan9011@gmail.com")
    .phoneNumber("+989333030XXX")
    .nationalCode("04400XXXXX")
    .create()

val secondPerson = Person.Builder(
    name = "Foroogh",
    family = "Varmazyar")
    .create()



参考



参考


Kotlin 语言中文站