在之前对Kotlin的反射进行了详细的学习,接下来进入一个全新的篇章,就是关于Koltin的协程【coroutine】,在正式撸码之前先对它有一个全面理论化的了解:

协程的定义:

  • 协程通过将复杂性放入库中来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。
  • 该库【协程是以单独的jar方式来存在的,如果项目中不用它则可以不依赖它】可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器)上调度执行,而代码则保持如同顺序执行一样简单

协程的描述:

  • 协程就像非常轻量级的线程。线程是由系统调度的,线程切换或线程阻塞的开销比较大。
  • 而协程依赖于线程,但是协程挂起时不需要阻塞线程,几乎是无代价的,协程是由开发者控制的。所以协程也像用户态的线程,非常轻量级,一个线程中可以创建任意个协程。
  •  总而言之:协程可以简化异步编程,可以顺序地表达程序,协程也提供了一种避免阻塞线程并用更廉价、更可控的操作替代线程阻塞的方法---协程挂起。

协程相关概念【了解,目前不可能记住的】:

  • CoroutineScope,可以理解为协程本身,包含了CoroutineContext。
  • CoroutineContext,协程上下文,是一些元素的集合,主要包括Job 和 CoroutineDispatcher元素,可以代表一个协程的场景。
  • EmptyCoroutineContext,表示一个空的协程上下文。
  • CoroutineDispatcher,协和调度器,决定协程所在的线程或线程池。它可以指定协程运行于特定的一个线程、一个线程池或者不指定任何线程(这样线程就会运行于当前线程)。
  • coroutines-core中CoroutineDispatcher有三种标准实现:Dispatchers.Default、Dispatchers.IO,Dispatchers.Main和Dispatchers.Unconfined,Unconfined就是不指定线程。
  • launch函数定义如果不指定CoroutineDispatcher或者没有其他的ContinuationInterceptor,默认的协程调度器就是Dispatchers.Default,Default是一个协程调度器,其指定的线程为共有的线程池,线程数量至少为2,最大与CPU数相同。

Job & Deferred:

  • Job,任务,封装了协程中需要执行的代码逻辑。Job可以取消并且有简单的生命周期,它有如下几种状态:
  • Android中kotlin的协程与线程有什么区别 android kotlin 协程_java


  • Job完成时是没有返回值的,如果需要返回值的话,应该使用Deferred,这是Job的子类。
  • public interface Deferred<out T> : Job

Coroutine builders:

  • CoroutineScope.launch函数属于协程构建器Coroutine builders,Koltin中还有其他几种Builders,负责创建协程。

CoroutineScope.launch{}:

  • CoroutineScope.launch{}是最常用的Coroutine builders,不阻塞当前线程,在后台创建一个新协程,也可以指定协程调度器。

runBlocking{}:

  • runBlocking{}是创建一个新的协程同时阻塞当前线程,直到协程结束。这个不应该在协程中使用,主要是为main函数和测试设计的。

withContext{}:

  • withContext{}不会创建新的协程,在指定协程上运行挂起代码块,并挂起该协程直至代码块运行完成。

async{}:

  • CoroutineScope.async{}可以实现与launch builder一样的效果,在后台创建一个新协程,唯一的区别是它有返回值,因为CoroutineScope.async{}返回的是Deferred类型。