Kotlin協程筆記

引入攜程所需庫

第一步:項目級build.gradle中

buildscript {
 ext.kotlin_coroutines = '1.3.1'
}

第二步:Module級別build.gradle中

dependencies {
 //                                       ?? 依賴協程核心庫
 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines"
 //                                       ?? 依賴當前平臺所對應的平臺庫,如Android或js
 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines"
 //協程的聲明周期庫,該庫可以選加,是讓協程的生命周期和Activity的周期保持一致
 implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.0-alpha02'
}

注:核心庫和平臺庫版本需要保持一致

協程是什么

  • 協程:是一個線程框架,最核心的部分是【非阻塞式】和【掛起】;就是launch{協程部分}async{協程部分}

相關名詞

1、GloabScope:全局范圍
2、Coroutine:協程
3、suspend:掛起、暫停

  • a、代碼執行到用suspend標識的函數時會掛起,且這種掛起是不會阻塞的,不會影響當前線程的執行,而這種所謂的掛起,其實就是切一個線程,且在函數執行完畢會自動將線程切回來的調度工作。
  • b、用suspend標識的函數只能運行在協程中;或者被另一個被suspend標識的函數調用,其實最終還是運行在一個協程中。
  • c、suspend本身是不能真正實現掛起的,他的作用主要是一個提醒,是創建者對使用者的提醒,該函數是一個耗時函數,且是用掛起的方式在后臺運行,所以請在協程中調用我
  • d、suspend的意義:傳遞CoroutineContext

相關方法介紹

runBlocking :一般用于 單元測試中,是線程阻塞的

launch(Dispatchers.IO){}:可以用來切線程

coroutineScope.launch(Dispatchers.IO) {
    ...
    launch(Dispatchers.Main){
        ...
        launch(Dispatchers.IO) {
            ...
            launch(Dispatchers.Main) {
                ...
            }
        }
    }
}

withContext(){}:切換線程,當需要頻繁的進行線程切換時,因為可以自動切回原來的線程,所以相應的代碼嵌套層次沒那么多,并在閉包內的邏輯執行結束后自動切回原來的線程,繼續執行

coroutineScope.launch(Dispatchers.Main) {
    ...
    withContext(Dispatchers.IO) {
        ...
    }
    ...
    withContext(Dispatchers.IO) {
        ...
    }
    ...
}

Async{}:返回的協程實現了Deferred??梢允褂脀ait()方法

創建攜程的方法

方法一:使用runBlocking 頂層函數,適用于單元測試的情況,是線程阻塞的,一般正常的業務開發不會使用

runBlocking{個人理解:此次相當于開啟一個線程,但是會阻塞當前線程,相當于一個耗時任務???
  getImage(imageId)
}

方法二:使用GlobalScope 單例對象,直接調用launch開啟協程,不會阻塞線程,但是實際開發中也一般不會使用,因為它的生命周期和APP的生命周期是一致的

GlobalScope.launch{
  getImage(imageId)
}

方法三:通過CoroutineContext創建一個CoroutineScope(接口)對象,需要一個類型為CoroutineContext的參數。開發中推薦這種方法,--coroutineContext?????

val coroutineScope = CoroutineScope(coroutineContext)
coroutineScope.launch{
  getImage(imageId)
}

方法四:主要用于在一個協程中開啟另一個協程,直接在普通代碼中無法使用

launch{
  
}

方法五:該方法與launch類似,也是在協程中使用

async{
  
}

async 和 launch對比

相同點:都可以用來啟動一個協程,返回的都是Coroutine

不同點:

  • async返回的Coroutine還實現了Deferred(意思是延遲,也就是結果稍后才能拿到。)接口。可以使用await暫停函數來返回result

  • launch可啟動新協程而不將結果返回給調用方

async使用場景:如現在需要展示公司LOGO和個人頭像,但是需要等待兩者都返回了,才可以去顯示,兩者同時進行,然后等較慢的執行完畢就可以顯示了,所花費的時間就是兩個中較長的一個,而不是兩者之和

coroutineScope.launch(Dispatchers.Main) {
    //                      ??  async 函數啟動新的協程
    val avatar: Deferred = async { api.getAvatar(user) }    // 獲取用戶頭像
    val logo: Deferred = async { api.getCompanyLogo(user) } // 獲取用戶所在公司的 logo
    //            ??          ?? 獲取返回值
    show(avatar.await(), logo.await())                     // 更新 UI
}

掛起的本質

什么是掛起:掛起就是稍后會自動切回來的操作

在協程中,我們掛起的對象既不是線程,也不是函數,而是我們掛起的對象是協程,就是launch和async函數中的閉包的代碼塊,而launch和async或者其他函數創建的協程在執行到某一個suspend函數的時候,這個函數就會被掛起,或者說從當前線程中脫離。

自定義suspend函數

  • 什么時候需要自定義suspend函數

    比如某個函數時比較函數的,可以將他協程suspend函數,這就是原則
    耗時操作分為:I/O操作和CPU計算工作,比如文件讀寫,網絡交互,圖片的模糊處理。
    另一種耗時操作:如事情本身并不慢,但是因為某些原因需要等5s或者特定時間再執行,這種也可以定義為suspend
    
  • 具體如何實現自定義

    1、給函數加上suspend關鍵字
    2、用withContext將函數內容包?。ǚ奖銏绦型戤叄詣忧谢卦季€程)
    3、針對需要等待的耗時操作,我們可以直接使用另一個掛起函數delay()
    
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374