Kotlin中協(xié)程的使用

官方介紹協(xié)程

協(xié)程定義

協(xié)程定義:kotlin官方基于JVM的線程實(shí)現(xiàn)的一個(gè)并發(fā)任務(wù)處理框架,封裝的線程api

  • 使用方便,不使用回調(diào)實(shí)現(xiàn)線程切換,使用同步方式寫(xiě)出異步代碼
  • 所有的耗時(shí)任務(wù)保證一定放在后臺(tái)執(zhí)行
  • 掛起函數(shù)執(zhí)行完畢之后,協(xié)程會(huì)把它切換到原先的線程的線程。

協(xié)程的基本用法

常規(guī)函數(shù)中一般都有:call and return,協(xié)程在此之外添加了suspend和resume.

  • suspend 用于暫停執(zhí)行的當(dāng)前協(xié)程,并保存所有的局部變量
  • resume 用于已暫停的協(xié)程中暫停出恢復(fù)

supend(掛起函數(shù))是什么,有什么意義

suspend,對(duì)協(xié)程的掛起并沒(méi)有實(shí)際作用,其實(shí)只是一個(gè)提醒,函數(shù)創(chuàng)建者對(duì)函數(shù)的調(diào)用者的提醒,提醒調(diào)用者我是需要耗時(shí)操作,需要用掛起的方式,在協(xié)程中使用.

  • 需要注意的是掛起函數(shù)只能在掛起函數(shù)或者協(xié)程作用域中使用,為什么掛起函數(shù)需要在協(xié)程作用域中使用?因?yàn)槠胀ê瘮?shù)沒(méi)有suspend和resume這兩個(gè)特性,所以必須要在協(xié)程的作用中使用。

意義:

  • 語(yǔ)法層面:作為一個(gè)標(biāo)記和提醒。通過(guò)報(bào)錯(cuò)來(lái)提醒調(diào)用者和編譯器,這是一個(gè)耗時(shí)函數(shù),需要放在后臺(tái)執(zhí)行。

  • 編譯器層面:輔助 Kotlin 編譯器來(lái)把代碼轉(zhuǎn)換成 JVM 的字節(jié)碼。

怎么自定義suspend函數(shù)?

  • 什么時(shí)候定義?

需要耗時(shí)操作的時(shí)候,需要定義,例如io耗時(shí)操作(請(qǐng)求網(wǎng)絡(luò));獲取數(shù)據(jù)庫(kù)數(shù)據(jù);一些等待一會(huì)需要的操作;列表排除,json解析等;

  • 怎么寫(xiě)suspend函數(shù)

給函數(shù)前加上suspend 關(guān)鍵字,把內(nèi)容用withContext包起來(lái)

suspend fun testSuspendfun(){
      withContext(Dispatchers.IO){

      }
  }

協(xié)程如何確保主線程安全

  • Dispatchers.Main 調(diào)用程序在Android的主線程中
  • Dispatchers.IO 適合主線程之外的執(zhí)行磁盤(pán)或者網(wǎng)絡(luò)io操作,例如文件的讀取與寫(xiě)入,任何的網(wǎng)絡(luò)請(qǐng)求
  • Dispatcher.Default 適合主線程之外的,cpu的操作,例如json數(shù)據(jù)的解析,以及列表的排序,

協(xié)程的掛起本質(zhì)

  • 本質(zhì)就是切線程,完成之后只不過(guò)可以自動(dòng)切回來(lái)

協(xié)程掛起就是切個(gè)線程,在掛起函數(shù)執(zhí)行完畢之后,協(xié)程會(huì)自動(dòng)的重新切回它原先的線程,也就是稍后會(huì)被切回來(lái)的線程切換。切回來(lái)就是resume,恢復(fù)功能是協(xié)程,所以suspend函數(shù)需要在另一個(gè)suspend函數(shù)或者協(xié)程中調(diào)用.

  • 什么是協(xié)程的「非阻塞式掛起」

阻塞的方式寫(xiě)出了非阻塞的方式

協(xié)程的創(chuàng)建以及取消

//創(chuàng)建一個(gè)協(xié)程

Val scope = CoroutineScope(Dispatchers.Main+Job())

通過(guò)Job獲取協(xié)程的生命周期

scope.launch{
}

其他耗時(shí)請(qǐng)求,例如從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)

 scope.async {
 }

在KTX庫(kù)為某些生命周期提供自己的CoroutineScope,例如ViewModel中viewModelScope,Lifecycle有l(wèi)ifecycleScope

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

  • launch 啟動(dòng)新協(xié)程而不將結(jié)果返回給調(diào)用方
//創(chuàng)建之后,不管后續(xù)
launch(){
}
  • async 啟動(dòng)一個(gè)新協(xié)程,并通過(guò)deferred的await方法暫停函數(shù)
//返回deferred 對(duì)象
val deferred async{

}
deferred.await()

協(xié)程的結(jié)構(gòu)化并發(fā),取消協(xié)程

協(xié)程的結(jié)構(gòu)化并發(fā),可以讓協(xié)程非常便于管理。例如在關(guān)閉activity中要取消協(xié)程。如果是在線程中,取消所有的線程比較復(fù)雜。

  • 取消父協(xié)程以及父里面的子協(xié)程
  val scope = CoroutineScope(Dispatchers.Main+ Job())
        scope.launch {
            val job = launch {

               val job1 =  launch {
                   
                }
            }
            job.cancel()
        }
        scope.cancel()
  • 取消子協(xié)程某一個(gè)

每一個(gè)協(xié)程都會(huì)返回一個(gè)job對(duì)象,通過(guò)調(diào)用job的cancle,可以去取消單個(gè)的協(xié)程的。

val scope = CoroutineScope(Dispatchers.Main+ Job())
        scope.launch {
            val job = launch {

               val job1 =  launch {
                   
                }
            }
            job.cancel()
        }
        scope.cancel()

協(xié)程中異常處理

  • 在協(xié)程內(nèi)部中捕獲異常
val scope = CoroutineScope(Dispatchers.Main+ Job())
        scope.launch {
            try {
                
            }catch (e:Exception){
            }
        }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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