Android Kotlin程序员

Kotlin中协程封装与取消

2019-02-14  本文已影响39人  涂山小狐妖

1. 将java中的回调接口封装成挂起函数

import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import java.io.IOException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

suspend fun Call.await(): String = suspendCoroutine { block ->
    enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            block.resumeWithException(e)
        }

        override fun onResponse(call: Call, response: Response) {
            if (response.isSuccessful) {
                block.resume(response.body()!!.string())
            }
        }
    })
}

val client: OkHttpClient = OkHttpClient.Builder() .build()
        val request: Request = Request.Builder()
            .get()
            .url("http://xxx")
            .build()
  GlobalScope.async(Dispatchers.Main) {
            val call = client.newCall(request)
            val data = call.await()
        }

因为Call的扩展函数await()是个挂起函数,所以必须运行在协程或者其他的挂起函数中

delay()函数

yield()函数:挂起当前协程,然后将协程分发到 Dispatcher 的队列,这样可以让该协程所在线程或线程池可以运行其他协程逻辑,然后在 Dispatcher 空闲的时候继续执行原来协程。简单的来说就是让出自己的执行权,给其他协程使用,当其他协程执行完成或也让出执行权时,一开始的协程可以恢复继续运行

2. 父子协程

GlobalScope.launch(Dispatchers.Main) {
            //父协程
            launch { 
                //子协程
            }
            async {
                //子协程 
            }
            withContext(coroutineContext){
                //子协程
            }
        }

3. 协程取消

fun main() = runBlocking {
    val job = launch {
        launch {
            repeat(6) {
                println("run_child:$it")
                delay(500)
            }
        }
        repeat(6) {
            println("run_parent:$it")
            delay(500)
        }
    }
    delay(1600)
    job.cancel()
    println("job end")

}
fun main() = runBlocking {
    val job = launch(Dispatchers.Default) {
        var nextTime = 0L
        var i = 1
        while (i <= 3) {
            val nowTime = System.currentTimeMillis()
            if (nowTime >= nextTime) {
                println("parent_${i++}")
                nextTime = nowTime + 500L
            }
        }
    }
    delay(800)
    job.cancel()
    println("job end")
}
fun main() = runBlocking {
    val job = launch(Dispatchers.Default) {
        var nextTime = 0L
        var i = 1
        while (isActive) {
            val nowTime = System.currentTimeMillis()
            if (nowTime >= nextTime) {
                println("parent_${i++}")
                nextTime = nowTime + 500L
            }
        }
    }

    delay(1200)
    job.cancel()
    println("job end")

}

4.超时取消

try {
    withTimeout(1300L) {
        repeat(1000) { i ->
                println("I'm sleeping $i ...")
            delay(500L)
        }
    }
} finally {
    println("I'm running finally")
}
val result = withTimeoutOrNull(1300L) {
    repeat(1000) { i ->
            println("I'm sleeping $i ...")
        delay(500L)
    }
    "Done" /* 在它运行得到结果之前取消它,如果循环次数x延迟时间小等于1300则返回Done,否则返回null*/
}
println("Result is $result")
上一篇 下一篇

猜你喜欢

热点阅读