成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

在之前的文章里,我們為各位開發者分享了在 Android 中使用協程的一些基礎知識,包括在 Android 協程的背景介紹上手指南代碼實戰。本次系列文章 "協程中的取消和異常" 也是 Android 協程相關的內容,我們將與大家深入探討協程中關于取消操作和異常處理的知識點和技巧。

[[332617]]

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

CoroutineScope

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

  • 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

當您希望在應用程序的某一個層次開啟或者控制協程的生命周期時,您需要創建一個 CoroutineScope。對于一些平臺,比如 Android,已經有 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

當創建 CoroutineScope 的時候,它會將 CoroutineContext 作為構造函數的參數。您可以通過下面代碼創建一個新的 scope 和協程:

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

Job

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

Job:

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

CoroutineContext

CoroutineContext 是一組用于定義協程行為的元素。它由如下幾項構成:

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

CoroutineContex:

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

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

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

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

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

△ 協程是以任務層級為序執行的。

父級是 CoroutineScope 或者其它協程

Job 的生命周期

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

△ Job 的生命周期

如果協程處于活躍狀態,協程運行出錯或者調用 job.cancel() 都會將當前任務置為取消中 (Cancelling) 狀態 (isActive = false, isCancelled = true)。當所有的子協程都完成后,協程會進入已取消 (Cancelled) 狀態,此時 isCompleted = true。

解析父級 CoroutineContext

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

父級上下文 = 默認值 + 繼承的 CoroutineContext + 參數

其中:

  • 一些元素包含默認值: Dispatchers.Default 是默認的 CoroutineDispatcher,以及 "coroutine" 作為默認的 CoroutineName;
  • 繼承的 CoroutineContext 是 CoroutineScope 或者其父協程的 CoroutineContext;
  • 傳入協程 builder 的參數的優先級高于繼承的上下文參數,因此會覆蓋對應的參數值。

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

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

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

 

新的 CoroutineContext = 父級 CoroutineContext + Job()

如果使用上圖中的 CoroutineScope ,我們可以像下面這樣創建新的協程:

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

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

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

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

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

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

【本文是51CTO專欄機構“谷歌開發者”的原創稿件,轉載請聯系原作者(微信公眾號:Google_Developers)】

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

 

 

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2020-07-09 10:03:07

Android 協程開發

2017-06-15 13:15:39

Python協程

2021-09-16 09:59:13

PythonJavaScript代碼

2021-04-25 09:36:20

Go協程線程

2023-11-17 11:36:59

協程纖程操作系統

2023-08-08 07:18:17

協程管道函數

2020-04-08 09:06:34

Android 協程開發

2020-02-24 10:39:55

Python函數線程池

2021-08-04 16:19:55

AndroidKotin協程Coroutines

2024-02-05 09:06:25

Python協程Asyncio庫

2024-06-27 07:56:49

2025-06-26 04:10:00

2021-09-10 17:02:43

Python協程goroutine

2022-11-21 06:55:08

golang協程

2023-11-26 18:35:25

Python編程語言

2020-06-19 08:01:48

Kotlin 協程編程

2023-10-24 19:37:34

協程Java

2017-09-22 16:08:16

Python協程編程

2025-06-03 00:00:02

Go協程鎖機制

2021-12-09 06:41:56

Python協程多并發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩在线不卡 | 青青草免费在线视频 | 国产免费一区二区三区 | 日韩成人在线播放 | 日韩第一区 | 欧美aaaaa| 国产欧美日韩在线观看 | 狠狠狠色丁香婷婷综合久久五月 | 国产高清一区二区三区 | 伊人网伊人 | 91精品国产91久久久久久 | 欧美激情网站 | 久久伊人在 | 亚洲91精品| 日日干日日 | www.成人免费视频 | www国产成人免费观看视频,深夜成人网 | 一区二区三区福利视频 | 91亚洲国产成人久久精品网站 | 国产操操操 | 自拍偷拍第一页 | 国产免费一区二区三区 | 欧美午夜精品理论片a级按摩 | 欧美精品一区二区三区四区 在线 | 我要看黄色录像一级片 | 99爱在线视频 | 亚洲精品在线看 | 日本一区二区高清视频 | 成人免费在线视频 | 欧美一区二区三区大片 | 嫩呦国产一区二区三区av | 日韩精品免费播放 | 99久久99久久精品国产片果冰 | 亚洲3p| 日本一区视频在线观看 | 毛片综合 | 激情欧美日韩一区二区 | 中文字幕 国产精品 | 日日摸日日碰夜夜爽亚洲精品蜜乳 | 亚洲福利av | 日韩中文字幕在线观看 |