自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

協(xié)程中的取消和異常 | 核心概念介紹

移動開發(fā) Android
本次系列文章 "協(xié)程中的取消和異常" 也是 Android 協(xié)程相關(guān)的內(nèi)容,我們將與大家深入探討協(xié)程中關(guān)于取消操作和異常處理的知識點和技巧。

在之前的文章里,我們?yōu)楦魑婚_發(fā)者分享了在 Android 中使用協(xié)程的一些基礎(chǔ)知識,包括在 Android 協(xié)程的背景介紹、上手指南代碼實戰(zhàn)。本次系列文章 "協(xié)程中的取消和異常" 也是 Android 協(xié)程相關(guān)的內(nèi)容,我們將與大家深入探討協(xié)程中關(guān)于取消操作和異常處理的知識點和技巧。

[[332617]]

當(dāng)我們需要避免多余的處理來減少內(nèi)存浪費并節(jié)省電量時,取消操作就顯得尤為重要;而妥善的異常處理也是提高用戶體驗的關(guān)鍵。本篇是另外兩篇文章的基礎(chǔ) (第二篇和第三篇將為大家分別詳解協(xié)程取消操作和異常處理), 所以有必要先講解一些協(xié)程的核心概念,比如 CoroutineScope (協(xié)程作用域)、Job (任務(wù)) 和 CoroutineContext (協(xié)程上下文),這樣我們才能夠進(jìn)行更深入的學(xué)習(xí)。

CoroutineScope

CoroutineScope 會追蹤每一個您通過 launch 或者 async 創(chuàng)建的協(xié)程 (這兩個是 CoroutineScope 的擴展函數(shù))。任何時候都可通過調(diào)用 scope.cancel() 來取消正在進(jìn)行的工作 (正在運行的協(xié)程)。

  • CoroutineScope:https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/
  • launch:https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
  • async:https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html

當(dāng)您希望在應(yīng)用程序的某一個層次開啟或者控制協(xié)程的生命周期時,您需要創(chuàng)建一個 CoroutineScope。對于一些平臺,比如 Android,已經(jīng)有 KTX 這樣的庫在一些類的生命周期里提供了 CoroutineScope,比如 viewModelScope 和 lifecycleScope。

  • viewModelScope:https://developer.android.google.cn/reference/kotlin/androidx/lifecycle/package-summary#(androidx.lifecycle.ViewModel).viewModelScope:kotlinx.coroutines.CoroutineScope
  • lifecycleScope:https://developer.android.google.cn/reference/kotlin/androidx/lifecycle/package-summary#lifecyclescope

當(dāng)創(chuàng)建 CoroutineScope 的時候,它會將 CoroutineContext 作為構(gòu)造函數(shù)的參數(shù)。您可以通過下面代碼創(chuàng)建一個新的 scope 和協(xié)程:

  1. //Job 和 Dispatcher 已經(jīng)被集成到了 CoroutineContext 
  2. //后面我們詳細(xì)介紹 
  3. val scope = CoroutineScope(Job() + Dispatchers.Main) 
  4.  
  5. val job = scope.launch { 
  6.     //新的協(xié)程 

Job

Job 用于處理協(xié)程。對于每一個您所創(chuàng)建的協(xié)程 (通過 launch 或者 async),它會返回一個 Job 實例,該實例是協(xié)程的唯一標(biāo)識,并且負(fù)責(zé)管理協(xié)程的生命周期。正如我們上面看到的,您可以將 Job 實例傳遞給 CoroutineScope 來控制其生命周期。

Job:

https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html

CoroutineContext

CoroutineContext 是一組用于定義協(xié)程行為的元素。它由如下幾項構(gòu)成:

  • Job:控制協(xié)程的生命周期;
  • CoroutineDispatcher:向合適的線程分發(fā)任務(wù);
  • CoroutineName:協(xié)程的名稱,調(diào)試的時候很有用;
  • CoroutineExceptionHandler:處理未被捕捉的異常,在未來的第三篇文章里會有詳細(xì)的講解。

CoroutineContex:

thttps://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-coroutine-context/index.html

那么對于新創(chuàng)建的協(xié)程,它的 CoroutineContext 是什么呢?我們已經(jīng)知道一個 Job 的實例會被創(chuàng)建,它會幫助我們控制協(xié)程的生命周期。而剩下的元素會從 CoroutineContext 的父類繼承,該父類可能是另外一個協(xié)程或者創(chuàng)建該協(xié)程的 CoroutineScope。

由于 CoroutineScope 可以創(chuàng)建協(xié)程,而且您可以在協(xié)程內(nèi)部創(chuàng)建更多的協(xié)程,因此內(nèi)部就會隱含一個任務(wù)層級。在下面的代碼片段中,除了通過 CoroutineScope 創(chuàng)建新的協(xié)程,來看看如何在協(xié)程中創(chuàng)建更多協(xié)程:

  1. val scope = CoroutineScope(Job() + Dispatchers.Main) 
  2.  
  3. val job = scope.launch { 
  4.     // 新的協(xié)程會將 CoroutineScope 作為父級 
  5.     val result = async { 
  6.         // 通過 launch 創(chuàng)建的新協(xié)程會將當(dāng)前協(xié)程作為父級 
  7.     }.await() 

層級的根通常是 CoroutineScope。圖形化該層級后如下圖所示:

△ 協(xié)程是以任務(wù)層級為序執(zhí)行的。

父級是 CoroutineScope 或者其它協(xié)程

Job 的生命周期

一個任務(wù)可以包含一系列狀態(tài): 新創(chuàng)建 (New)、活躍 (Active)、完成中 (Completing)、已完成 (Completed)、取消中 (Cancelling) 和已取消 (Cancelled)。雖然我們無法直接訪問這些狀態(tài),但是我們可以訪問 Job 的屬性: isActive、isCancelled 和 isCompleted。

△ Job 的生命周期

如果協(xié)程處于活躍狀態(tài),協(xié)程運行出錯或者調(diào)用 job.cancel() 都會將當(dāng)前任務(wù)置為取消中 (Cancelling) 狀態(tài) (isActive = false, isCancelled = true)。當(dāng)所有的子協(xié)程都完成后,協(xié)程會進(jìn)入已取消 (Cancelled) 狀態(tài),此時 isCompleted = true。

解析父級 CoroutineContext

在任務(wù)層級中,每個協(xié)程都會有一個父級對象,要么是 CoroutineScope 或者另外一個 coroutine。然而,實際上協(xié)程的父級 CoroutineContext 和父級協(xié)程的 CoroutineContext 是不一樣的,因為有如下的公式:

父級上下文 = 默認(rèn)值 + 繼承的 CoroutineContext + 參數(shù)

其中:

  • 一些元素包含默認(rèn)值: Dispatchers.Default 是默認(rèn)的 CoroutineDispatcher,以及 "coroutine" 作為默認(rèn)的 CoroutineName;
  • 繼承的 CoroutineContext 是 CoroutineScope 或者其父協(xié)程的 CoroutineContext;
  • 傳入?yún)f(xié)程 builder 的參數(shù)的優(yōu)先級高于繼承的上下文參數(shù),因此會覆蓋對應(yīng)的參數(shù)值。

請注意: CoroutineContext 可以使用 " + " 運算符進(jìn)行合并。由于 CoroutineContext 是由一組元素組成的,所以加號右側(cè)的元素會覆蓋加號左側(cè)的元素,進(jìn)而組成新創(chuàng)建的 CoroutineContext。比如,(Dispatchers.Main, "name") + (Dispatchers.IO) = (Dispatchers.IO, "name")。

Dispatchers.IO:http://dispatchers.io/

該 CoroutineScope 所創(chuàng)建的每一個協(xié)程,CoroutineContext 至少會包含這些元素。這里的 CoroutineName 是灰色的,因為該值源于默認(rèn)參數(shù)值。那么現(xiàn)在我們明白新協(xié)程的父級 CoroutineContext 是什么樣的了,它實際的 CoroutineContext 是:

 

新的 CoroutineContext = 父級 CoroutineContext + Job()

如果使用上圖中的 CoroutineScope ,我們可以像下面這樣創(chuàng)建新的協(xié)程:

  1. val job = scope.launch(Dispatchers.IO) { 
  2.     //新協(xié)程 

而該協(xié)程的父級 CoroutineContext 和它實際的 CoroutineContext 是什么樣的呢?請看下面這張圖。

CoroutineContext 里的 Job 和父級上下文里的不可能是通過一個實例,因為新的協(xié)程總會拿到一個 Job 的新實例。

最終的父級 CoroutineContext 會內(nèi)含 Dispatchers.IO 而不是 scope 對象里的 CoroutineDispatcher,因為它被協(xié)程的 builder 里的參數(shù)覆蓋了。此外,注意一下父級 CoroutineContext 里的 Job 是 scope 對象的 Job (紅色),而新的 Job 實例 (綠色) 會賦值給新的協(xié)程的 CoroutineContext。

在我們這個系列的第三部分中,CoroutineScope 會有另外一個 Job 的實現(xiàn)稱為 SupervisorJob 被包含在其 CoroutineContext 中,該對象改變了 CoroutineScope 處理異常的方式。因此,由該 scope 對象創(chuàng)建的新協(xié)程會將一個 SupervisorJob 作為其父級 Job。不過,當(dāng)一個協(xié)程的父級是另外一個協(xié)程時,父級的 Job 會仍然是 Job 類型。

現(xiàn)在,大家了解了協(xié)程的一些基本概念,在接下來的文章中,我們將在第二篇繼續(xù)深入探討協(xié)程的取消、第三篇探討協(xié)程的異常處理,感興趣的讀者請繼續(xù)關(guān)注我們的更新。

【本文是51CTO專欄機構(gòu)“谷歌開發(fā)者”的原創(chuàng)稿件,轉(zhuǎn)載請聯(lián)系原作者(微信公眾號:Google_Developers)】

戳這里,看該作者更多好文

 

 

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2020-07-09 10:03:07

Android 協(xié)程開發(fā)

2017-06-15 13:15:39

Python協(xié)程

2021-09-16 09:59:13

PythonJavaScript代碼

2021-04-25 09:36:20

Go協(xié)程線程

2023-08-08 07:18:17

協(xié)程管道函數(shù)

2023-11-17 11:36:59

協(xié)程纖程操作系統(tǒng)

2020-04-08 09:06:34

Android 協(xié)程開發(fā)

2020-02-24 10:39:55

Python函數(shù)線程池

2021-08-04 16:19:55

AndroidKotin協(xié)程Coroutines

2024-02-05 09:06:25

Python協(xié)程Asyncio庫

2021-09-10 17:02:43

Python協(xié)程goroutine

2022-11-21 06:55:08

golang協(xié)程

2023-11-26 18:35:25

Python編程語言

2020-06-19 08:01:48

Kotlin 協(xié)程編程

2024-06-27 07:56:49

2025-02-08 09:13:40

2023-10-24 19:37:34

協(xié)程Java

2021-12-09 06:41:56

Python協(xié)程多并發(fā)

2017-09-22 16:08:16

Python協(xié)程編程

2024-12-03 15:15:22

點贊
收藏

51CTO技術(shù)棧公眾號