程async)
Android Kotlin 協(xié)程asyncmeasureTimeMillis 統(tǒng)計(jì)一段代碼耗時(shí)內(nèi)斂函數(shù) measureTimeMillis{ } 可以很方便的統(tǒng)計(jì)一段代碼執(zhí)行的耗時(shí)。使用GlobalScope.launch { val time measureTimeMillis { delay(1000) Log.d(zyj-, 日志) } Log.d(zyj-, 耗時(shí):$time) }輸出結(jié)果D/zyj-: 日志 D/zyj-: 耗時(shí):1010使用默認(rèn)順序定義兩個(gè)耗時(shí)函數(shù)suspend fun doSomethingUsefulOne(): Int { delay(1000L) // 假設(shè)我們?cè)谶@里做了一些有用的事 return 13 } suspend fun doSomethingUsefulTwo(): Int { delay(1000L) // 假設(shè)我們?cè)谶@里也做了一些有用的事 return 29 }使用默認(rèn)的順序調(diào)用val time measureTimeMillis { val one doSomethingUsefulOne() val two doSomethingUsefulTwo() println(The answer is ${one two}) } println(Completed in $time ms)它的打印輸出如下The answer is 42 Completed in 2017 ms從輸出結(jié)果上看兩個(gè)耗時(shí)任務(wù)是串行的總耗時(shí) 耗時(shí)函數(shù)1 耗時(shí)函數(shù)2使用 async 并發(fā)如果 doSomethingUsefulOne 與 doSomethingUsefulTwo 之間沒有依賴并且我們想更快的得到結(jié)果讓它們進(jìn)行 并發(fā) 嗎這就是async 可以幫助我們的地方。在概念上async 就類似于 launch。它啟動(dòng)了一個(gè)單獨(dú)的協(xié)程與其它所有的協(xié)程一起并發(fā)的工作。不同之處在于 launch 返回一個(gè) Job 并且不附帶任何結(jié)果值而 async 返回一個(gè) Deferred—— 一個(gè)非阻塞 future 這代表了一個(gè)將會(huì)在稍后提供結(jié)果的 promise。你可以使用 .await()在一個(gè)延期的值上得到它的最終結(jié)果 但是 Deferred 也是一個(gè) Job所以如果需要的話你可以取消它。val time measureTimeMillis { val one async { doSomethingUsefulOne() } val two async { doSomethingUsefulTwo() } println(The answer is ${one.await() two.await()}) } println(Completed in $time ms)它的打印輸出如下The answer is 42 Completed in 1017 ms這里快了兩倍因?yàn)閮蓚€(gè)協(xié)程并發(fā)執(zhí)行。 請(qǐng)注意使用協(xié)程進(jìn)行并發(fā)總是顯式的。惰性啟動(dòng)的 async可選的async 可以通過將 start 參數(shù)設(shè)置為 CoroutineStart.LAZY 而變?yōu)槎栊缘摹?在這個(gè)模式下只有結(jié)果通過 await 獲取的時(shí)候協(xié)程才會(huì)啟動(dòng)或者在 Job 的 start函數(shù)調(diào)用的時(shí)候。運(yùn)行下面的示例val time measureTimeMillis { val one async(start CoroutineStart.LAZY) { doSomethingUsefulOne() } val two async(start CoroutineStart.LAZY) { doSomethingUsefulTwo() } // 執(zhí)行一些計(jì)算 one.start() // 啟動(dòng)第一個(gè) two.start() // 啟動(dòng)第二個(gè) println(The answer is ${one.await() two.await()}) } println(Completed in $time ms)它的打印輸出如下The answer is 42 Completed in 1017 ms因此在先前的例子中這里定義的兩個(gè)協(xié)程沒有執(zhí)行但是控制權(quán)在于程序員準(zhǔn)確的在開始執(zhí)行時(shí)調(diào)用 start。我們首先 調(diào)用 one然后調(diào)用 two接下來等待這個(gè)協(xié)程執(zhí)行完畢。注意如果我們只是在 println 中調(diào)用 await而沒有在單獨(dú)的協(xié)程中調(diào)用 start這將會(huì)導(dǎo)致順序行為直到 await 啟動(dòng)該協(xié)程 執(zhí)行并等待至它結(jié)束這并不是惰性的預(yù)期用例。 在計(jì)算一個(gè)值涉及掛起函數(shù)時(shí)這個(gè) async(start CoroutineStart.LAZY)的用例用于替代標(biāo)準(zhǔn)庫中的 lazy 函數(shù)。構(gòu)建async 風(fēng)格的函數(shù)我們可以定義異步風(fēng)格的函數(shù)來 異步 的調(diào)用 doSomethingUsefulOne 和 doSomethingUsefulTwo 并使用 async 協(xié)程建造器并帶有一個(gè)顯式的 GlobalScope 引用。 我們給這樣的函數(shù)的名稱中加上“……Async”后綴來突出表明事實(shí)上它們只做異步計(jì)算并且需要使用延期的值來獲得結(jié)果。// somethingUsefulOneAsync 函數(shù)的返回值類型是 DeferredInt fun somethingUsefulOneAsync() GlobalScope.async { doSomethingUsefulOne() } // somethingUsefulTwoAsync 函數(shù)的返回值類型是 DeferredInt fun somethingUsefulTwoAsync() GlobalScope.async { doSomethingUsefulTwo() }使用class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 我們可以在協(xié)程外面啟動(dòng)異步執(zhí)行 val one somethingUsefulOneAsync() val two somethingUsefulTwoAsync() // 但是等待結(jié)果必須調(diào)用其它的掛起或者阻塞 // 當(dāng)我們等待結(jié)果的時(shí)候這里我們使用 GlobalScope.launch{ } 來阻塞主線程 GlobalScope.launch { println(The- answer is ${one.await()} ${two.await()}) } } }這種帶有異步函數(shù)的編程風(fēng)格僅供參考因?yàn)檫@在其它編程語言中是一種受歡迎的風(fēng)格。在 Kotlin 的協(xié)程中使用這種風(fēng)格是強(qiáng)烈不推薦的 原因如下所述??紤]一下如果 val one somethingUsefulOneAsync() 這一行和 one.await() 表達(dá)式這里在代碼中有邏輯錯(cuò)誤 并且程序拋出了異常以及程序在操作的過程中中止將會(huì)發(fā)生什么。 通常情況下一個(gè)全局的異常處理者會(huì)捕獲這個(gè)異常將異常打印成日記并報(bào)告給開發(fā)者但是反之該程序?qū)?huì)繼續(xù)執(zhí)行其它操作。但是這里我們的 somethingUsefulOneAsync仍然在后臺(tái)執(zhí)行 盡管如此啟動(dòng)它的那次操作也會(huì)被終止。這個(gè)程序?qū)⒉粫?huì)進(jìn)行結(jié)構(gòu)化并發(fā)如下一小節(jié)所示。使用 async 的結(jié)構(gòu)化并發(fā)讓我們使用使用 async 的并發(fā)這一小節(jié)的例子并且提取出一個(gè)函數(shù)并發(fā)的調(diào)用 doSomethingUsefulOne 與 doSomethingUsefulTwo 并且返回它們兩個(gè)的結(jié)果之和。 由于 async 被定義為了 CoroutineScope上的擴(kuò)展我們需要將它寫在作用域內(nèi)并且這是 coroutineScope 函數(shù)所提供的suspend fun concurrentSum(): Int coroutineScope { val one async { doSomethingUsefulOne() } val two async { doSomethingUsefulTwo() } one.await() two.await() }這種情況下如果在 concurrentSum 函數(shù)內(nèi)部發(fā)生了錯(cuò)誤并且它拋出了一個(gè)異常 所有在作用域中啟動(dòng)的協(xié)程都會(huì)被取消。val time measureTimeMillis { println(The answer is ${concurrentSum()}) } println(Completed in $time ms)從上面的 main 函數(shù)的輸出可以看出我們?nèi)匀豢梢酝瑫r(shí)執(zhí)行這兩個(gè)操作The answer is 42 Completed in 1017 ms取消始終通過協(xié)程的層次結(jié)構(gòu)來進(jìn)行傳遞import kotlinx.coroutines.* fun main() runBlockingUnit { try { failedConcurrentSum() } catch(e: ArithmeticException) { println(Computation failed with ArithmeticException) } } suspend fun failedConcurrentSum(): Int coroutineScope { val one asyncInt { try { delay(Long.MAX_VALUE) // 模擬一個(gè)長時(shí)間的運(yùn)算 42 } finally { println(First child was cancelled) } } val two asyncInt { println(Second child throws an exception) throw ArithmeticException() } one.await() two.await() }請(qǐng)注意如果其中一個(gè)子協(xié)程即 two失敗第一個(gè) async 以及等待中的父協(xié)程都會(huì)被取消Second child throws an exception First child was cancelled Computation failed with ArithmeticException后文Android Kotlin 更多學(xué)習(xí)資料可以掃碼免費(fèi)領(lǐng)取《史上最詳Android版kotlin協(xié)程入門進(jìn)階實(shí)戰(zhàn)》第一章 Kotlin協(xié)程的基礎(chǔ)介紹? ● 協(xié)程是什么? ● 什么是Job 、Deferred 、協(xié)程作用域? ● Kotlin協(xié)程的基礎(chǔ)用法第二章 kotlin協(xié)程的關(guān)鍵知識(shí)點(diǎn)初步講解? ● 協(xié)程調(diào)度器? ● 協(xié)程上下文? ● 協(xié)程啟動(dòng)模式? ● 協(xié)程作用域? ● 掛起函數(shù)第三章 kotlin協(xié)程的異常處理? ● 協(xié)程異常的產(chǎn)生流程? ● 協(xié)程的異常處理第四章 kotlin協(xié)程在Android中的基礎(chǔ)應(yīng)用? ● Android使用kotlin協(xié)程? ● 在Activity與Framgent中使用協(xié)程? ● ViewModel中使用協(xié)程? ● 其他環(huán)境下使用協(xié)程第五章 kotlin協(xié)程的網(wǎng)絡(luò)請(qǐng)求封裝? ● 協(xié)程的常用環(huán)境? ● 協(xié)程在網(wǎng)絡(luò)請(qǐng)求下的封裝及使用? ● 高階函數(shù)方式? ● 多狀態(tài)函數(shù)返回值方式第六章 深入kotlin協(xié)程原理一? ● suspend的花花腸子? ● 藏在身后的-Continuation? ● 村里的希望-SuspendLambda第七章 深入kotlin協(xié)程原理二? ● 協(xié)程的那些小秘密? ● 協(xié)程的創(chuàng)建過程? ● 協(xié)程的掛起與恢復(fù)? ● 協(xié)程的執(zhí)行與狀態(tài)機(jī)第八章 Kotlin Jetpack 實(shí)戰(zhàn)? ● 從一個(gè)膜拜大神的 Demo 開始? ● Kotlin 寫 Gradle 腳本是一種什么體驗(yàn)? ● Kotlin 編程的三重境界? ● Kotlin 高階函數(shù)? ● Kotlin 泛型? ● Kotlin 擴(kuò)展? ● Kotlin 委托? ● 協(xié)程“不為人知”的調(diào)試技巧? ● 圖解協(xié)程原理第九章 Kotlin 協(xié)程 Retrofit MVVM優(yōu)雅的實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求? ● 項(xiàng)目配置? ● 實(shí)現(xiàn)思路? ● 協(xié)程實(shí)現(xiàn)? ● 協(xié)程 ViewModel LiveData實(shí)現(xiàn)? ● 后續(xù)優(yōu)化? ● 異常處理? ● 更新Retrofit 2.6.0由于文章內(nèi)容比較多篇幅有限資料已經(jīng)被整理成了PDF文檔有需要 Android中高級(jí)面試必知必會(huì) 完整文檔的可以加微信可免費(fèi)領(lǐng)取!承諾100%免費(fèi)更有更多資料加微信免費(fèi)領(lǐng)取