Kotlin

《Android Kotlin協(xié)程實(shí)戰(zhàn)》

https://www.bilibili.com/video/BV1uo4y1y7ZF/?spm_id_from=333.999.0.0&vd_source=b5ef87e2f0a873011363576f8bdcba61
動(dòng)腦學(xué)院 你能聽(tīng)懂的Kotlin協(xié)程課潘酗,跟老司機(jī)學(xué)停蕉,不用自己瞎折騰

###1.認(rèn)識(shí)協(xié)程
協(xié)程是什么津函?協(xié)程基于線(xiàn)程,它是輕量級(jí)線(xiàn)程
異步任務(wù)和協(xié)程對(duì)比缝裁? 協(xié)程讓異步邏輯同步化枢贿,杜絕回調(diào)地獄瑰抵,協(xié)程的核心是函數(shù)或者一段程序能夠被掛起暇榴,稍后再在掛起的位置恢復(fù)
協(xié)程的依賴(lài): kotlinx-coroutines-core, kotlinx-coroutines-android

協(xié)程的掛起與恢復(fù): suspend: 暫停執(zhí)行當(dāng)前協(xié)程,并保存所有的局部變量尤仍; resume:讓已暫停的協(xié)程從其暫停處繼續(xù)執(zhí)行
掛起函數(shù):suspend關(guān)鍵字修飾箫津,只能在協(xié)程體內(nèi)或其他掛起函數(shù)內(nèi)調(diào)用
掛起和阻塞的區(qū)別? 主線(xiàn)程遇到掛起(如協(xié)程里調(diào)用了delay)宰啦,先記下掛起點(diǎn)苏遥,然后該干嘛干嘛压语,如刷新UI学辱,等掛起結(jié)束了您访,繼續(xù)執(zhí)行下面呻逆; 
            主線(xiàn)程如果阻塞了(如Thread.sleep),就啥事不干驰吓,一直等結(jié)束(阻塞就是線(xiàn)程被占用了提完,不能干其他事情)
            Choreographer: Skipped xxx frames! The application may be doing too much work on its main thead.
協(xié)程兩部分:基礎(chǔ)設(shè)施層和業(yè)務(wù)框架層
    基礎(chǔ)設(shè)施層代碼實(shí)例: val continuation=suspend {5}.createCoroutine(object : Continuation<Int> {override fun resumeWith(result: Result<Int>) {}}); continuation.resume(Unit)

協(xié)程調(diào)度器:
    Dispatchers.Main : Android上的主線(xiàn)程
    Dispatcher.IO: 非主線(xiàn)程
    Dispatcher.Default 非主線(xiàn)程宋列,專(zhuān)為CPU密集型任務(wù)進(jìn)行了優(yōu)化

協(xié)程作用域:
    CoroutineScope: 會(huì)跟蹤所有協(xié)程辆布,同樣可以取消它所啟動(dòng)的所有協(xié)程
    GlobalScope: 生命周期是process級(jí)別的瞬矩,即使Activity或Fragment已經(jīng)被銷(xiāo)毀,協(xié)程仍然在執(zhí)行
    MainScope:在Activity中使用锋玲,可以在onDestory中取消協(xié)程景用,cancel()方法,取消會(huì)報(bào)異常JobCancellationException: Job was cancelled;
    viewModelScope: 只能在ViewModel中使用惭蹂,綁定ViewModel的生命周期
    lifecycleScope:只能在Activity或Fragment中使用伞插,會(huì)綁定Activity和Fragment的生命周期

###2.協(xié)程的啟動(dòng)與取消
協(xié)程構(gòu)建器:
    launch: 返回一個(gè)Job并且不附帶任何結(jié)果
    async:返回一個(gè)Deferred割粮,Deferred也是一個(gè)Job,可以使用await在一個(gè)延期的值上得到最終的結(jié)果
    等待上一個(gè)任務(wù)執(zhí)行完:launch+join(); async+await()
    runBlocking {} 讓我們的主線(xiàn)程變成一個(gè)協(xié)程
協(xié)程的啟動(dòng)模式:
    CoroutineStart.DEFAULT: 協(xié)程創(chuàng)建后蜂怎,立即開(kāi)始調(diào)度穆刻,在調(diào)度前協(xié)程如果被取消,其將直接進(jìn)入取消響應(yīng)的狀態(tài)
    CoroutineStart.ATOMIC: 協(xié)程創(chuàng)建后杠步,立即開(kāi)始調(diào)度,協(xié)程執(zhí)行到第一個(gè)掛起點(diǎn)之前不響應(yīng)取消
    CoroutineStart.LAZY: 只有協(xié)程被需要時(shí)榜轿,包括主動(dòng)調(diào)用協(xié)程的start幽歼,join或者await函數(shù)時(shí)才會(huì)開(kāi)始調(diào)度,如果調(diào)度前就被取消谬盐,那么該協(xié)程將直接進(jìn)入異常結(jié)束狀態(tài)
    CoroutineStart.UNDISPATCHED: 協(xié)程創(chuàng)建后立即在當(dāng)前函數(shù)調(diào)用棧中執(zhí)行甸私,直到遇到第一個(gè)真正掛起的點(diǎn)
如何指定協(xié)程上下文是Dispatchers.IO, 但是協(xié)程任務(wù)的執(zhí)行仍然還在主線(xiàn)程? 執(zhí)行協(xié)程啟動(dòng)模式為CoroutineStart.UNDISPATCHED 
協(xié)程作用域構(gòu)建器:
    coroutineScope與runBlocking
    runBlocking是常規(guī)函數(shù)飞傀,coroutineScope是掛起函數(shù)
Job對(duì)象
    對(duì)于每一個(gè)創(chuàng)建的協(xié)程(通過(guò)launch或者async)皇型,會(huì)返回一個(gè)Job實(shí)例,負(fù)責(zé)管理協(xié)程的生命周期
    新創(chuàng)建New砸烦,活躍Active弃鸦, 完成中Completing,已完成Completed幢痘,取消中Cancelling唬格,已取消Cancelled,可以訪問(wèn)Job的屬性:isActive颜说,isCancelled和isCompleted
取消協(xié)程:
    取消作用域會(huì)取消它的子協(xié)程购岗;被取消的子協(xié)程不會(huì)影響其余兄弟協(xié)程;協(xié)程通過(guò)拋出一個(gè)特殊的異常CancellationException來(lái)處理取消操作
CPU密集型任務(wù)取消
    isActive檢查Job是否處于活躍狀態(tài)门粪;ensureActive(),如果job處于非活躍狀態(tài)會(huì)立即拋出異常喊积;yield函數(shù)如果取消會(huì)拋出CancellationException異常,還會(huì)嘗試出讓線(xiàn)程的執(zhí)行權(quán)
    use函數(shù):只能被實(shí)現(xiàn)了Closeable的對(duì)象使用玄妈,程序結(jié)束的時(shí)候會(huì)自動(dòng)調(diào)用close方法乾吻,適合文件對(duì)象 
    不想?yún)f(xié)程被取消: withContext(NonCancellable) {} 
    超時(shí)任務(wù):withTimeout(1000) {}; withTimeoutOrNull(1000) {}
    
###3.協(xié)程的異常處理
    協(xié)程上下文CoroutineContext是一組定義協(xié)程行為的元素
        Job:控制協(xié)程的生命周期
        CoroutineDispatcher: 向合適的線(xiàn)程分發(fā)任務(wù)
        CoroutineName: 協(xié)程的名稱(chēng)
        CoroutineExceptionHandler: 處理未被捕獲的異常

    組合協(xié)程上下文: launch(Dispatchers.Default + CoroutineName("test")) {}  --重載了加號(hào)運(yùn)算符
    協(xié)程上下文的繼承:CoroutineScope協(xié)程作用域-》launch協(xié)程-》async子協(xié)程
            新創(chuàng)建的協(xié)程,它的CoroutineContext會(huì)包含一個(gè)全新的Job實(shí)例措近,剩下的元素從CoroutineContext的父類(lèi)繼承溶弟,該父類(lèi)可能是另外一個(gè)協(xié)程或者創(chuàng)建該協(xié)程的CoroutineScope
            
    根協(xié)程異常傳播:launch里拋出的異常:可以在launch協(xié)程里捕捉;async里拋出的異常瞭郑,調(diào)用await后才能捕捉
    非根協(xié)程的異常:其他協(xié)程創(chuàng)建的協(xié)程中辜御,產(chǎn)生的異常總是會(huì)被傳播
    異常的傳播特性:當(dāng)一個(gè)協(xié)程由于異常運(yùn)行失敗時(shí)屈张,它會(huì)傳播這個(gè)異常并傳遞給它的父級(jí)擒权,接下來(lái)父級(jí)會(huì)取消它自己的子級(jí)袱巨,取消它自己,將異常傳播并傳遞給它的父級(jí)
    SupervisorJob: 一個(gè)子協(xié)程的運(yùn)行失敗不會(huì)影響到其他子協(xié)程碳抄,SupervisorJob不會(huì)傳播異常給它的父級(jí)愉老,它會(huì)讓子協(xié)程自己處理異常
        CoroutineScope(SupervisorJob())
        作用域構(gòu)建器supervisorScope {}, 在supervisorScope里創(chuàng)建的子協(xié)程里拋出異常,不會(huì)影響其他子協(xié)程剖效;如果在supervisorScope作用域里拋出異常嫉入,所有子作業(yè)將會(huì)被全部取消
    異常的捕獲:使用CoroutineExceptionHandler對(duì)協(xié)程的異常進(jìn)行捕獲
    取消與異常:取消(如joinAndCancel)會(huì)拋出CancellationException異常,當(dāng)子協(xié)程被取消時(shí)璧尸,不會(huì)取消它的父協(xié)程
    異常聚合:CoroutineExceptionHandler { _, exception-> ${exception.suppressed.contentToString() --打印第二個(gè)異常}}

###4.Flow-異步流
    異步返回多個(gè)值: flow<Int> {  }咒林,
    flow: Flow構(gòu)建器函數(shù); flow{...} 構(gòu)建快中代碼可以?huà)炱穑?流使用emit函數(shù)發(fā)送值爷光; 使用collect函數(shù)收集值
    Flow應(yīng)用: Background Thread emit數(shù)據(jù) -》Main Thread 去collect數(shù)據(jù)
    冷流: flow構(gòu)建器中的代碼直到流被收集的時(shí)候才運(yùn)行
    流構(gòu)建器: 
        flowOf()發(fā)射固定值的流
        使用asFlow擴(kuò)展函數(shù)垫竞,可以將各種集合與序列轉(zhuǎn)換成流: (1..3).asFlow().collect { value -> println(value) }
    流的上下文:flowOn操作符:用于更改流發(fā)射的上下文; launchIn指定在那個(gè)協(xié)程里收集數(shù)據(jù)
    流的取消: withTimeoutOrNull(2500) {}
    流的取消檢測(cè): 流構(gòu)建器對(duì)每個(gè)發(fā)射值執(zhí)行附加的ensureActive檢測(cè)以進(jìn)行取消
        如果想流可以被取消蛀序,需要明確指定cancellable:  (1..5).asFlow().cancellable().collect { value -> if (value == 3) cancel() }
    背壓: 生產(chǎn)者生產(chǎn)效率大于消費(fèi)者消費(fèi)效率
        buffer() 并發(fā)運(yùn)行流中發(fā)射元素的代碼
        conflate() 合并發(fā)射項(xiàng)欢瞪; collectLatest() 
    操作符: 轉(zhuǎn)換操作符: map, transform; 限長(zhǎng)操作符:take; 
         末端操作符: reduce ; 1到5平方并累加 (1..5).asFlow().map{ it*it }.reduce{ a,b->a+b }
    組合多個(gè)流: zip
    展平流: flatMapConcat連接模式, flatMapMerge合并模式, flatMapLatest最新展平模式
    流的異常: 收集的時(shí)候處理異常: 如check(value <= 1) {} ; 發(fā)射的時(shí)候拋出異常徐裸,使用catch函數(shù)捕捉
    流的完成: onCompletion

    
    
        
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末遣鼓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子倦逐,更是在濱河造成了極大的恐慌譬正,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件檬姥,死亡現(xiàn)場(chǎng)離奇詭異曾我,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)健民,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)抒巢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人秉犹,你說(shuō)我怎么就攤上這事蛉谜。” “怎么了崇堵?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵型诚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我鸳劳,道長(zhǎng)狰贯,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮涵紊,結(jié)果婚禮上傍妒,老公的妹妹穿的比我還像新娘。我一直安慰自己摸柄,他們只是感情好颤练,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著驱负,像睡著了一般嗦玖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上跃脊,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天踏揣,我揣著相機(jī)與錄音,去河邊找鬼匾乓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛又谋,可吹牛的內(nèi)容都是我干的拼缝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼彰亥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼咧七!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起任斋,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤继阻,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后废酷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瘟檩,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年澈蟆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了墨辛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趴俘,死狀恐怖睹簇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寥闪,我是刑警寧澤太惠,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站疲憋,受9級(jí)特大地震影響凿渊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一嗽元、第九天 我趴在偏房一處隱蔽的房頂上張望敛纲。 院中可真熱鬧,春花似錦剂癌、人聲如沸淤翔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)旁壮。三九已至,卻和暖如春谐檀,著一層夾襖步出監(jiān)牢的瞬間抡谐,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工桐猬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留麦撵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓溃肪,卻偏偏與公主長(zhǎng)得像免胃,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惫撰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容