美文网首页
[学习]拥抱kotlin(四)

[学习]拥抱kotlin(四)

作者: 吴敬悦 | 来源:发表于2021-02-07 16:46 被阅读0次

接下来的 kotlin 学习的会以我学习 android 所遇到不会的进行学习。今天学习协程。还有扔物线的教程Kotlin 的协程用力瞥一眼 - 学不会协程?很可能因为你看过的教程都是错的

1. 准备工作

这里我只说在 gradle 中的配置,其他见:kotlin 中文教程(协程地址)

dependencies {
    ...
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
}

这个包在 jcenter() 仓库中。

2. 简单的示例

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

fun main(args: Array<String>) {
    println("Start")

    // 启动第一个协程
    GlobalScope.launch {
        delay(2000)
        println("Hello")
    }
    // 启动第二个协程
    GlobalScope.launch {
        delay(1000)
        println("World")
    }

    Thread.sleep(3000) // 等待 3 秒钟
    println("Stop")
}
// 输出的结果为: 
// Start
// World
// Hello
// Stop

协程的开启方式就是 launch 。其中 delay 就是延迟的意思,传入的参数是毫秒。

我们使用了类似 Thread.sleep() 的 delay() 函数,但是它更优异:它 不会阻塞一个线程 ,但是会挂起协程自身。 当这个协程处于等待状态时该线程会返回线程池中,当等待结束的时候,这个协程会在线程池中的空闲线程上恢复。

3. suspend 修饰的函数

这样的函数只能在协程中执行,上面的 delay 函数也是 suspend 修饰的。同时 suspend 也是一个协程。

fun main(args: Array<String>) {
    println("Start")
    GlobalScope.launch {
        delay(1000)
        println("World")
        println(testAsyc())
    }
    Thread.sleep(3000) // 等待 3 秒钟
    println("Stop")
}
suspend fun testAsyc(): Int {
    delay(1000)
    return 54
}

其中 asynclauch 差不多,但是也有区别, async 会返回一个 Deferred<T> 实例,而 lauch 不是。 Deferred<T> 实例打印如下:

val sha = GlobalScope.async {
    delay(1000)
    println("wujingyue")
}
println(sha) // 打印: DeferredCoroutine{Completed}@4d76f3f8

虽然使用 sha.await() 来得到返回结果,但 await 函数是一个 suspend 函数,这种函数只能在协程中执行,我这里的主线程并没有 suspend 修饰,固然不能正常调用。

fun main(args: Array<String>) {
    println("Start")
    val sha = GlobalScope.async {
        delay(1000)
        println("wujingyue")
    }
    GlobalScope.launch {
        println(sha.await())//输出为:kotlin.Unit
    }
    Thread.sleep(3000) // 等待 3 秒钟
    println("Stop")
}

还有一个 runBlocking 也可以创建协程:

fun main(args: Array<String>) {
    println("Start")
    runBlocking {
        val deferred = (1..1_000_000).map { n ->
            GlobalScope.async {
                delay(3000)
                n
            }
        }
        val sum = deferred.sumOf { it.await().toLong() }
        println("Sum: $sum")
    }
    Thread.sleep(3000) // 等待 3 秒钟
    println("Stop")
}
suspend fun testAsyc(): Int {
    delay(1000)
    return 54
}
// 输出:
// Start
// Sum: 500000500000
// Stop

在这个例子中我刻意这样 GlobalScope.async { delay(3000) n } ,我这样的目的是看看先执行 Stop 还是输出 Sum: 500000500000 ,结果可以看出先输出 Sum: 500000500000 ,这就说明了 runBlocking 是阻塞的,并不是挂起,所谓挂起是指遇到以后先不执行,以后再执行,至于以后什么时候执行我现在暂时还不知道。只不过现在就看看:

fun main(args: Array<String>) {
    println("Start")
    GlobalScope.launch {
        delay(1000)
        println("第一次")
    }
    GlobalScope.launch {
        delay(1000)
        println("第二次")
    }
    GlobalScope.launch {
        delay(1000)
        println("第三次")
    }
    Thread.sleep(3000) // 等待 3 秒钟
    println("Stop")
}
// 输出:
// Start
// 第二次
// 第一次
// 第三次

经过多次输出,发现并不是固定的,所以挂起以后什么时候执行是未知的。
可能我们还有这样的需求,就是所有的异步中,必须等待其中一个异步完成才能做下面的工作,那就这样。

suspend fun main(args: Array<String>) {
    println("Start")
    GlobalScope.launch {
        println("第一次")
    }
    val n = GlobalScope.launch {
        delay(10000)
        println("第N次")
    }
    n.join()
    println("Stop")
}

其中的 n.join() 就是了,意思就是等 n 这个协程完成以后再干活。我就比较喜欢等后台写完接口再干活,因为写界面非常简单,有数据了才写感觉很爽,不然的话自己造的数据最后还要根据后台变动而变动,所以一般两种情况我会进入开发,第一后台接口好了, UI 好了,第二就是数据格式定义好了, UI 好了;如果 UI 很复杂的话,我可以先把底子打好然后再写。

相关文章

  • [学习]拥抱kotlin(四)

    接下来的 kotlin 学习的会以我学习 android 所遇到不会的进行学习。今天学习协程。还有扔物线的教程Ko...

  • [学习]拥抱kotlin(七)

    我发现我在平时的使用中,连数组,集合很多我都非常懵逼,明明在 java 或 javascript 中都是很容易的。...

  • [学习]拥抱kotlin(Infix)

    我遇到了 Infix 函数。尽量一个就是一天,下次找的时候方便。 有了这个函数就相当于自己定义了一种操作,跟自定义...

  • [学习]拥抱kotlin(二)

    1. 字符串模版 字符串模版现在很多语言都是支持的,比如说: php 和 js 等等。虽然 java 也可以用,但...

  • [学习]拥抱kotlin(三)

    终于到类了,有一篇文章写得挺好的,Kotlin 里那些「更方便的」[https://kaixue.io/kotli...

  • [学习]拥抱kotlin(一)

    既然选择学习了,那就学习最新的,学习最时髦的;同时也为了兼容 java ,我到时候都尽量把两种都写一写。 1. 通...

  • [学习]拥抱kotlin(六)

    今天看委托模式。有一篇讲得不错的: 一文彻底搞懂Kotlin中的委托[https://juejin.cn/post...

  • [学习]拥抱kotlin(五)

    看 码上开学[https://kaixue.io/] 的视频记录。 1. 变量 如果你在写变量的时候是这样的 va...

  • Kotlin学习(四)

    对象表达式 在设置点击事件的时候常常会用到匿名类部类,在kotlin中匿名类部类表示如下: 对象声明 在Kotli...

  • Kotlin 学习四

    一: 区间、数组、集合① 区间(或叫作范围) ② 数组 Array ③ 集合 二: for 循环语句 三:whil...

网友评论

      本文标题:[学习]拥抱kotlin(四)

      本文链接:https://www.haomeiwen.com/subject/xlqztltx.html