Kotlin的協程


個人博客

http://www.milovetingting.cn

Kotlin的協程

前言

本文是Kotlin協程的一個簡單筆記,由於剛接觸Kotlin語言,如有理解錯誤,為避免誤導別人,可留言評論,以便本人及時修改,感謝各位大佬!關於協程的進階文章,可參考其它相關資料!

協程是什么

協程是一種並發設計模式,在 Android 平台上使用它來簡化異步執行的代碼。

以上是官方文檔對協程的簡單定義。

下面通過代碼來展示協程的具體使用。

假設有以下的需求:有一個耗時的任務要執行,在執行完成后,需要在主線程刷新UI。

不使用協程

在Activity的onCreate中分別調用以下方法


io()

ui()

private fun io() {
        thread {
            Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
            delay(1000)
        }
    }

    private fun ui() {
        Log.d(TAG, "ui method,thread:${Thread.currentThread().name}")
    }

輸出日志:

2020-09-25 23:10:25.854 5208-5208/com.wangyz.coroutines D/Coroutine: ui method,thread:main
2020-09-25 23:10:25.855 5208-5267/com.wangyz.coroutines D/Coroutine: io method,thread:Thread-2

分別調用io()和ui()方法,兩個方法分別運行在子線程和主線程中,但是由於子線程的耗時操作,主線程方法先執行了,這樣就沒有達到我們想要的順序執行的效果。

修改代碼:

io2()

private fun io2() {
        thread {
            Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
            delay(1000)
            runOnUiThread {
                ui2()
            }
        }
    }

    private fun ui2() {
        Log.d(TAG, "ui method,thread:${Thread.currentThread().name}")
    }

在子線程中通過runOnUiThread將線程切換到主線程中來,輸出結果:

2020-09-25 23:16:44.753 5597-5641/com.wangyz.coroutines D/Coroutine: io method,thread:Thread-2
2020-09-25 23:16:45.756 5597-5597/com.wangyz.coroutines D/Coroutine: ui method,thread:main

再來看下協程的實現方式

使用協程

依賴項信息

如需在Android項目中使用協程,需要將以下依賴項添加到應用的 build.gradle 文件中:

dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}

協程的使用

GlobalScope.launch(Dispatchers.Main) {
            io3()
            ui3()
        }

private suspend fun io3(){
        withContext(Dispatchers.IO){
            Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
            delay(1000)
        }
    }

    private fun ui3() {
        Log.d(TAG, "ui method,thread:${Thread.currentThread().name}")
    }

通過launch方法開啟一個協程,通過設置Dispatchers.Main運行在Main線程中,在io3中,通過withContext開啟一個線程,並通過設置Dispatchers.IO運行在IO線程。suspend是一個標記,表示這個方法內部會有掛起的操作,它並不會導致線程切換,真正切換線程是通過withContext來切換的。

輸出結果:

2020-09-25 23:28:19.965 6017-6062/com.wangyz.coroutines D/Coroutine: io method,thread:DefaultDispatcher-worker-1
2020-09-25 23:28:20.969 6017-6017/com.wangyz.coroutines D/Coroutine: ui method,thread:main

假設我們需要同時請求多個接口,並在這些接口全部返回數據后再統一更新界面,下面用協程來模擬實現這個需求。

請求多個異步接口

GlobalScope.launch(Dispatchers.Main) {
            val res1 = async { io4() }
            val res2 = async { io5() }
            val data = res1.await() + res2.await()
            ui4(data)
        }

private suspend fun io4() = withContext(
        Dispatchers.IO
    ) {
        delay(2000)
        Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
        1
    }

    private suspend fun io5() = withContext(
        Dispatchers.IO
    ) {
        delay(3000)
        Log.d(TAG, "io method,thread:${Thread.currentThread().name}")
        2
    }

    private fun ui4(value: Int) {
        Log.d(TAG, "ui method,thread:${Thread.currentThread().name},result:${value}")
    }

輸出結果:

2020-09-25 23:51:28.161 6495-6536/com.wangyz.coroutines D/Coroutine: io method,thread:DefaultDispatcher-worker-1
2020-09-25 23:51:29.389 6495-6537/com.wangyz.coroutines D/Coroutine: io method,thread:DefaultDispatcher-worker-2
2020-09-25 23:51:29.390 6495-6495/com.wangyz.coroutines D/Coroutine: ui method,thread:main,result:3

方法io4執行2秒,方法io5執行3秒,在io5執行完成后,將他們的結果相加再通過ui4更新到UI上。

參考

https://developer.android.google.cn/kotlin/coroutines


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM