Hi 各位好,又到了我們一年一度的 iT邦鐵人賽的挑戰,這次我所挑戰的主題是 Kotlin 中用來處理非同步的 lib Coroutine,中文名稱「協程」,是與 Kotlin 1.3 版一起推出的一個函式庫,正式版推出時間距今已經快要有三年的時間,目前在 github 也已經累積 9.7k 顆星。
Coroutine 推出之後,很多 Kotlin 開發者開始使用 Coroutine,究竟 Coroutine 有什麼樣的魅力,可以讓 Kotlin 開發者對 Coroutines 趨之若鶩呢?
在三十天中,我們將會一一討論 Coroutine,包括 CoroutineScope、Coroutine Builder、Suspend function、channel、flow... 。
在開始進行 Coroutine 的討論之前,我們要先來了解 Coroutine 是要用來解決什麼問題。(文末解答XD)
首先,根據程式的執行順序可以分為兩種形式,一種是同步 (Synchronous)的、另一種為非同步(Asynchronous),也稱為異步。
同步是根據程式碼的順序來執行。同步的程式是容易的、直覺的,只要將程式碼按照想要執行的順序依序編寫就可以了。
如上, 用同步的方式依序執行三段程式,程式的執行時間就會是 function A 所執行的時間+ function B 所執行的時間 + function C 所執行的時間。一段程式執行完之後,才會執行下一段程式。
這就像是田徑場上的接力賽的感覺,一棒接一棒。
非同步的概念則是與同步相異,程式碼不是依照程式碼的順序來執行並得到結果。當需要執行的程式需要比較多的時間,為了避免卡住畫面,會將程式碼在另外的執行緒上執行,等到完成之後告訴主執行緒、又或者是不知道什麼時候可以取得結果(例如與 Server 取值)。
如下圖,向 Server 取值的時序圖:
當 Client 向 Server 發出一個請求時,因為是採用非同步的方式執行,所以在發出請求之後,還可以做其他的操作,Client 不會卡在那邊等 Server 的值回傳。
若改用同步的方式來實現,執行時序圖如下:
可以發現,如果採用同步的方式來取 Server 的值,假設 API 需要花費比較長的時間才會得到結果,那麼用戶端就會卡在那邊,等待 Server 的回傳值,更不用說如果等待的時間拉長,會嚴重影響使用的體驗。在 Android 上,只要主執行緒 (Main Thread) 停住五秒鐘以上,就會顯示 ANR (Application Not Response)來警告使用者。
所以當執行這些結果不是立刻取得的任務時,為了避免不會因執行太久、等待太久而導致使用者使用體驗不好,我們會使用非同步的方式來處理。
簡單來說,非同步的概念就是我請別人幫忙做事,別人做完之後再通知我。那麼這樣子就不會佔用到主執行緒,當然如果非同步執行的程式需要花費很多時間,非同步應該要可以隨時被停止,Coroutine 在這一點就做得蠻好的。
除了耗時任務以外,有些時候我們需要延遲執行我們的程式,也就是說當我們呼叫的時候這段程式碼不會立刻執行,而是等待一段時間才繼續執行,並回傳結果,
介紹了同步以及非同步的差異,聰明的讀者你應該已經猜到了,沒錯,Coroutine 就是用來解決非同步的種種問題。
Kotlin Taiwan User Group
Kotlin 讀書會
有興趣的讀者歡迎參考:https://coroutine.kotlin.tips/
天瓏書局
大大介紹同步與非同步
寫的淺顯易懂!! 讚讚!!
小小建議
最後一張心智圖的中心 "同步/非同步"
跟拉出去的線是相反的,左邊是非同步,右邊是同步
有可能會記錯它們的特性唷