抬头仰望星空,是否能发现自己的渺小。

伪斜杠青年

人们总是混淆了欲望和理想

Kotlin协程的一点初体验

欲善其事,必利其器的问题在于

很多时候并不知道什么器才是好的器

这两天用协程改造老旧代码,效果还是很显著的,git更改情况2000行大概是这样:

当然后面删得更多了,之前项目使用的是promise,但是这个promise for kotlin已经很久没更新了,大概是歪果仁追求新很早就用得了协程,用不着再造轮子了。

需求

整理下了需求,大概就是,需要能接收异常,需要在启动时能指定线程,希望有一个总是被执行的alwaysUI块,能简化的处理UI与IO的切换那么这样:

定义一个类文件,将以下代码作为顶级函数:

fun CoroutineScope.launchWithExceptionCatch(context: CoroutineContext = EmptyCoroutineContext,
                                            exceptionBlock: ((throwable: Throwable) -> Unit)? = null,
                                            alwaysUi: (() -> Unit)? = null,
                                            block: suspend CoroutineScope.() -> Unit) {
    launch(context + CoroutineExceptionHandler { coroutineContext, throwable ->
        //主要是alwaysUi异常记录
        Log.e(TAG, "parent block context:${coroutineContext} exception:$throwable")
    }) {
        try {
            //协程代码块 默认主线程
            block()
        } catch (e: Exception) {
            //防止因为生命周期导致的退出影响异常处理逻辑
            if (e is CancellationException) return@launch
            Log.e(TAG, "sub block exception:$e")
            //协程代码块异常处理
            exceptionBlock?.invoke(e)
        }
        //alwaysUi处理
        withUI { alwaysUi?.invoke() }
    }
}

suspend fun <T> withUI(block: suspend CoroutineScope.() -> T): T {
    return withContext(Dispatchers.Main, block)
}

suspend fun <T> withIO(block: suspend CoroutineScope.() -> T): T {
    return withContext(Dispatchers.IO, block)
}

那么,用的时候:

lifecycleScope.launchWithExceptionCatch(Dispatchers.IO, exceptionBlock = { throwable ->
//有点东西抛出了
}, alwaysUi = {
//按钮被禁用了 无论成功失败都得重新启用
}) {
//目前启动的时候已经是IO了 切个UI?
val res = withUI {
// 显示个弹窗?返回个数据?
"hello"
}
//做点耗时
delay(3000)
//显示一下
withUI { toastShort(res) }
}

或者:

lifecycleScope.launchWithExceptionCatch(exceptionBlock = { throwable ->
    //有点东西抛出了
}, alwaysUi = {
    //按钮被禁用了 无论成功失败都得重新启用
}) {
    //目前启动的时候啥都没指定 切个IO?
    val res = withIO {
        //做点耗时 返回个数据?
        delay(3000)
        "hello"
    }
    //显示一下
    withUI { toastShort(res) }
}

在kotlin这个协程里,还可以做点事儿,比如官方封好的withTimeOut、async …

以及一些特殊场景下使用的suspendCoroutine,flow等,挺香的。

总结

一种将异步代码当同步代码写的 语法糖

参考:https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/


0条评论

发表评论