前言
协程是一个并发方案。也是一种思想。
传统意义上的协程是单线程的,面对io密集型任务他的内存消耗更少,进而效率高。但是面对计算密集型的任务不如多线程并行运算效率高。
不同的语言对于协程都有不同的实现,甚至同一种语言对于不同平台的操作系统都有对应的实现。
我们kotlin语言的协程是 coroutines for jvm的实现方式。底层原理也是利用java 线程。
基础知识
生态架构
相关依赖库
dependencies {
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.32"
// 协程核心库
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
// 协程Android支持库
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3"
// 协程Java8支持库
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.4.3"
// lifecycle对于协程的扩展封装
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
}
为什么一些人总觉得协程晦涩难懂?
1.网络上没有详细的关于协程的概念定义,每种语言、每个系统对其实现都不一样。可谓是众说纷纭,什么内核态用户态巴拉巴拉,很容易给我们带偏
2.kotlin的各种语法糖对我们造成的干扰。如:
- 高阶函数
- 源码实现类找不到
所以扎实的kotlin语法基本功是学习协程的前提。
实在看不懂得地方就反编译为java,以java最终翻译为准。
协程是什么?有什么用?
kotlin中的协程干的事就是把异步回调代码拍扁了,捋直了,让异步回调代码同步化。除此之外,没有任何特别之处。
创建一个协程,就是编译器背后偷偷生成一系列代码,比如说状态机。
通过挂起和恢复让状态机状态流转实现把层层嵌套的回调代码变成像同步代码那样直观、简洁。
它不是什么线程框架,也不是什么高深的内核态,用户态。它其实对于咱们安卓来说,就是一个关于回调函数的语法糖。。。
本文将会围绕挂起与恢复彻底剖析协程的实现原理
Kotlin函数基础知识复习
再Kotlin中函数是一等公民,有自己的类型
函数类型
fun foo(){}
//类型为 () -> Unit
fun foo(p: Int){}
//类型为 (Int) -> String
class Foo{
fun bar(p0: String,p1: Long):Any{}
}
//那么 bar 的类型为:Foo.(String,Long) -> Any
//Foo就是bar的 receiver。也可以写成 (Foo,String,Long) ->Any
函数引用
fun foo(){}
//引用是 ::foo
fun foo(p0: Int): String
//引用也是 ::foo
咋都一样?没办法,就这样规定的。使用的时候 只能靠编译器推断
val f: () -> Unit = ::foo //编译器会推断出是fun foo(){}
val g: (Int) -> String = ::foo //推断为fun foo(p0: Int): String
带Receiver的写法
class Foo{
fun bar(p0: String,p1: Long):Any{}
}
val h: (Foo,String,Long) -> Any = Foo:bar
绑定receiver的函数引用:
val foo: Foo = Foo()
val m: (String,Long) -> Any = foo:bar
额外知识点
val x: (Foo,String,Long) -> Any = Foo:bar
val y: Function3<Foo,String,Long,Any> = x
Foo.(String,Long) -> Any = (Foo,String,Long) ->Any = Function3<Foo,String,Long,Any>
函数作为参数传递
fun yy(p: (Foo,String,Long)->Any){
p(Foo(),"Hello",3L)//直接p()就能调用
//p.invoke(Foo(),"Hello",3L) 也可以用invoke形式
}
Lambda
就是匿名函数,它跟普通函数比是没有名字的,听起来好像是废话
//普通函数
fun func(){
println("hello");
}
//去掉函数名 func,就成了匿名函数
fun(){
println("hello");
}
//可以赋值给一个变量
val func = fun(){
println("hel