Androdi kotlin Coroutines(協(xié)程)詳解 (二)

Androdi kotlin Coroutines(協(xié)程)詳解 (一)
Androdi kotlin Coroutines(協(xié)程)詳解 (二)
Androdi kotlin Coroutines(協(xié)程)詳解 (三)
Androdi kotlin Coroutines(協(xié)程)詳解 (四)
Androdi kotlin Coroutines(協(xié)程)詳解 (五)
Androdi kotlin Coroutines(協(xié)程)詳解 (六)

二、協(xié)程的啟動(dòng)

build.gradle 引入?yún)f(xié)程庫

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7" //協(xié)程核心庫
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7" //Android協(xié)程擴(kuò)展庫

2.1 啟動(dòng)方法

2.1.1 GlobalScope啟動(dòng)
GlobalScope.launch {
  //to do some thing
}

GlobalScope 實(shí)現(xiàn)了接口 CoroutineScope ,而 CoroutineScope 有 launch 方法,不阻塞線程
相關(guān)的源碼如下:

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
          LazyStandaloneCoroutine(newContext, block) 
        else
          StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

比如下面的代碼:

    fun startCoroutineByGlobeScope() {
        println("start execute ${Thread.currentThread().name}")
        GlobalScope.launch {
            println("launch start execute ${Thread.currentThread().name}")
            delay(1000)
            println("launch end execute ${Thread.currentThread().name}")
        }
        println("end execute ${Thread.currentThread().name}")
        Thread.sleep(2000)
    }

運(yùn)行結(jié)果:

start execute main
end execute main
launch start execute DefaultDispatcher-worker-1 @coroutine#1
launch end execute DefaultDispatcher-worker-1 @coroutine#1

Job

后臺(tái)的工作。從概念上講,作業(yè)是一種可取消的東西,它的生命周期最終將完成。Job 可以取消并且有簡單生命周期,它有三種狀態(tài):

State [isActive] [isCompleted] [isCancelled]
New (optional initial state) false false false
Active (default initial state) true false false
Completing (optional transient state) true false false
Cancelling (optional transient state) false false true
Cancelled (final state) false true true
Completed (final state) false true false
//Job中的方法
job.isActive //是否存活
job.isCancelled //是否關(guān)閉
job.isCompleted //是否完成
job.cancel() //關(guān)閉
job.join() //掛起協(xié)程直到執(zhí)行完畢
job.start() //開始執(zhí)行
2.1.2 CoroutineScope啟動(dòng)
CoroutineScope(context = EmptyCoroutineContext).launch {
  // to do something
}
2.1.3 runBlocking {}啟動(dòng)

runBlocking {}是創(chuàng)建一個(gè)新的協(xié)程同時(shí)阻塞當(dāng)前線程,直到協(xié)程結(jié)束。這個(gè)不應(yīng)該在協(xié)程中使用,主要是為main函數(shù)和測試設(shè)計(jì)的。

private fun runBlockingCoroutine() {
  println("runBlockingCoroutine start work thread ${Thread.currentThread().name}")
        runBlocking {
            delay(1000)
            println("runBlockingCoroutine ${Thread.currentThread().name}")
        }
  println("runBlocking end work thread ${Thread.currentThread().name}")
}
2.1.4 實(shí)現(xiàn)CoroutineScope接口,初始化上下文

如GlobalScope 是 CoroutineScope 的一個(gè)單例實(shí)現(xiàn)


2.2 四種啟動(dòng)方式 CoroutineStart

public enum class CoroutineStart {
  DEFAULT,
  LAZY,
  @ExperimentalCoroutinesApi
  ATOMIC,
  @ExperimentalCoroutinesApi
  UNDISPATCHED;
}
模式 功能
DEFAULT 立即執(zhí)行協(xié)程體
LAZY 懶漢式,只有在需要的情況下運(yùn)行
ATOMIC 立即執(zhí)行協(xié)程體,但在開始運(yùn)行之前無法取消,實(shí)驗(yàn)api
UNDISPATCHED 立即在當(dāng)前線程執(zhí)行協(xié)程體,直到第一個(gè) suspend 調(diào)用,實(shí)驗(yàn)api
2.2.1 DEFAULT

DEFAULT 是餓漢式啟動(dòng), launch 調(diào)用后,會(huì)立即進(jìn)入待調(diào)度狀態(tài),一旦調(diào)度器 OK 就可以開始執(zhí)行。
示例:

  Log.d(TAG, " oncreate start")
  GlobalScope.launch(start = CoroutineStart.DEFAULT) {
  Log.d(TAG, "block start")
  for (i in 1..5) {
    Log.d(TAG, "num is $i")
    delay(500)
  }
  Log.d(TAG, "block end")
}
Log.d(TAG, " oncreate end")

運(yùn)行結(jié)果:

D/TestActivity: oncreate start
D/TestActivity: oncreate end
D/TestActivity: block start
D/TestActivity: num is 1
D/TestActivity: num is 2
D/TestActivity: num is 3
D/TestActivity: num is 4
D/TestActivity: num is 5
D/TestActivity: block end
2.2.2 LAZY

LAZY 是懶漢式啟動(dòng), launch 后并不會(huì)有任何調(diào)度行為,協(xié)程體也自然不會(huì)進(jìn)入執(zhí)行狀態(tài),直到我們需要它執(zhí)行的時(shí)候。這其實(shí)就有點(diǎn)兒費(fèi)解了,什么叫我們需要它執(zhí)行的時(shí)候呢?就是需要它的運(yùn)行結(jié)果的時(shí)候, launch 調(diào)用后會(huì)返回一個(gè) Job 實(shí)例,對(duì)于這種情況,我們可以:

  • 調(diào)用 Job.start ,主動(dòng)觸發(fā)協(xié)程的調(diào)度執(zhí)行
  • 調(diào)用 Job.join ,隱式的觸發(fā)協(xié)程的調(diào)度執(zhí)行
  Log.d(TAG, " oncreate start")
  val job = GlobalScope.launch(start = CoroutineStart.LAZY) {
  Log.d(TAG, "block start")
  for (i in 1..5) {
      Log.d(TAG, "num is $i")
      delay(500)
   }
   Log.d(TAG, "block end")
  }
  job.start()
  Log.d(TAG, " oncreate end")
2.2.3 ATOMIC

ATOMIC 只有涉及 cancel 的時(shí)候才有意義,在這里我們就簡單認(rèn)為 cancel 后協(xié)程會(huì)被取消掉,也就是不再執(zhí)行了。那么調(diào)用cancel 的時(shí)機(jī)不同,結(jié)果也是有差異的,例如協(xié)程調(diào)度之前、開始調(diào)度但尚未執(zhí)行、已經(jīng)開始執(zhí)行、執(zhí)行完畢等等。

  Log.d(TAG, " oncreate start")
  val job = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
  Log.d(TAG, "block start")
  for (i in 1..5) {
    Log.d(TAG, "num is $i")
    delay(500)
  }
  Log.d(TAG, "block end")
  }
  job.cancel()
  Log.d(TAG, " oncreate end")
2.2.4 UNDISPATCHED

協(xié)程在這種模式下會(huì)直接開始在當(dāng)前線程下執(zhí)行,直到第一個(gè)掛起點(diǎn),這聽起來有點(diǎn)兒像前面的 ATOMIC ,不同之處在于UNDISPATCHED 不經(jīng)過任何調(diào)度器即開始執(zhí)行協(xié)程體。當(dāng)然遇到掛起點(diǎn)之后的執(zhí)行就取決于掛起點(diǎn)本身的邏輯以及上下文當(dāng)中的調(diào)度器了。

        Log.d(TAG, " oncreate start")
        val job = GlobalScope.launch(start = CoroutineStart.UNDISPATCHED) {
            Log.d(TAG, "block start")
            for (i in 1..5) {
                Log.d(TAG, "num is $i")
                delay(500)
            }
            Log.d(TAG, "block end")
        }
        Log.d(TAG, " oncreate job.start")
        job.start()
        Log.d(TAG, " oncreate end")
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容