Kotlin 协程学习,实战解析

代码变得十分简单优雅~

这就是传说中的 非阻塞式挂起的魅力。这个概念很后面再说。

注:它和Dart语言中的那个不一样哦。

因为其使用lambda表达式,所以代码风格简洁,效率又高,下面一节可读可不读。

1.3 Lambda表达式和匿名内部类的区别


该节可读可不读。

注:Kotlin出现时,Java还在6/7,这也是为什么Kotlin从一开始就被提倡应用于Android开发的一个小小的原因(因为Java还没有Lambda表达式)

在使用协程(以及很大一部分代码块)的时候,我们经常会用到Lambda表达式。

我们为什么用它?

  • 简洁好写

  • 减少样板代码

但是你以为这就是它的好处吗?我之前一直搞不懂为什么仅仅是实现一个函数式编程,却能成为Java8新特性中必须要吹、必须要学的知识,而究其原因其实是:

Lambda函数(如果不捕获)在运行时产生,在使用时作为单例对象(私有方法)存在,重用时不会产生其他开销,而匿名内部类则在每次调用都要加载并实例化成一个对象。

这句话有点高度概括。

需要知道Java是如何去编译匿名内部类的,在我之前学习热修复的时候热修复原理学习(3)编译器与语言特性的影响学习过 内部类在编译期会被编译为跟外部类一样的顶级类,匿名内部类也是内部类,所以它会走和类一样的加载-使用-垃圾回收的过程,而Lambda表达式则是在运行时产生一个调用的函数入口。

所以使用 Lambda表达式 是完爆 使用匿名内部类的。

这里的捕获指的是该Lambda使用了其作用域之外的变量,可以将其视为私有字段的类中的函数,而不捕获指的Lambda就是纯函数。

2. 开启协程的三个基础方法

================================================================================

在Kotlin本来的包中时没有协程api的,所以要在build.gradle中引入:

// build.gradle

implementation “org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version”

implementation “org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version”

协程的入口是 launch{} 语句块,但它不是顶层函数,所以不能直接使用,有三种实现,分别来看看他们来实现Hello World

2.1 使用GlobalScope.launch实现


使用 GlobalScope.launch 可以手动开启一个协程:

fun main() {

println(“Thread name:” + Thread.currentThread().name)

GlobalScope.launch { // 在后台启动一个新的协程并继续

println(“Coroutines Thread name:” + Thread.currentThread().name)

delay(100L) // 假设这是一个100ms耗时任务

println(“World!”) // 这是耗时任务的结果

}

println(“Hello,”) // 主线程中的代码会立即执行

Thread.sleep(200L) // 延迟 200 毫秒来保证 JVM 的存活

}

// 打印:

Thread name:main

Hello,

Coroutines Thread name:DefaultDispatcher-worker-1

World!

在开启的协程中,我们使用 delay来让协程挂起100ms后答应world,表明这是一个耗时的任务。

主线程中输入了Hello后,使用Thread.sleep()来阻塞主线程,防止在协程的任务还没执行完时,主线程就关闭了。

这个时候我们会发现,协程所在的线程和外边线程不一致。

2.2 使用runBlocking实现


runBlocking{..}代码块里面,就是协程。相比于GlobalScope,它是阻塞线程的,一般开发中我们用不到,常用于单元测试,来看一下使用语句块实现:

fun main() {

println(“Thread name:” + Thread.currentThread().name)

runBlocking {

println(“Coroutines Thread name:” + Thread.currentThread().name)

delay(1000L)

print("Hello, ")

}

print(“World!”)

}

// 打印结果:

Thread name:main

Coroutines Thread name:main

Hello, World

可以看到 runBlocking{...}开启了一个协程,但是他没有在新线程里面执行,而是一直阻塞到里面的代码块完成。

可以来看下下面的用法:

fun main() = runBlocking { // 使用runBlocking开启一个协程

launch { // 里面再开启一个协程

delay(1000L)

println("World! " + Thread.currentThread().name)

}

println("Hello, " + Thread.currentThread().name)

}

// 打印结果:

Hello, main

World! main

这个代码中,我们在 runBlocking{}里,又开启了一个launch协程,相当于大协程里面的小协程。

我们没有使用 Thread.sleep()来防止主线程执行完而launch中的代码还没有执行的问题,它依然能够等所有任务都执行完后才关闭程序。

上面两片代码可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值