Kotlin 个人小工具集

Kotlin 协程

一,异步操作(仿RxJava)
Android APP中,使用RxJava在很多时候都很方便,但是从apk包解析来看,RxJava的包有点大。。。 所以自从用了Kotlin之后,我已经想着怎么把Rxjava从项目中删除掉。 一般我使用RxJava更多的是用来进行异步处理,比如说是在非UI线程中处理耗时操作,然后在UI线程中处理结果,使用Kotlin的协程也可以达到类似效果。

fun <R> processOnAsync(action: () -> R,
                       success: (R) -> Unit,
                       fail: (Throwable) -> Unit): Job {
    return launch {
        val result = suspendCancellableCoroutine<R> { continuation ->
            continuation.invokeOnCompletion {
                if (continuation.isCancelled) {
                    NonCancellable.cancel()
                }
            }

            if (continuation.isActive) {
                try {
                    continuation.resume(action())
                } catch (exp: Throwable) {
                    continuation.resumeWithException(exp)
                }
            }
        }

        launch (UI) {//将结果返回到UI线程中
            when (result) {
                is Throwable -> {
                    fail(result)
                }
                else -> {
                    success(result)
                }
            }
        }
    }
}
复制代码

使用方法:

    processOnAsync({
        //耗时操作,注意这里返回的是最后一行,或者使用return来指定返回
    }, success = {
        //成功时的处理代码
    }, fail = {
        //失败时的处理代码
    })
复制代码

(仿异步操作还有别的方法,比如组合async和launch来实现也可以)

二,另一种异步操作
如果需要实现的功能是:在一个异步操作中一直等待结果,再把这个结果返回。那么(一)就无法满足了,只能使用如下方法:

fun <R> processWithAsync(block: (CancellableContinuation<R>) -> Unit,
                         success: (R) -> Unit,
                         fail: (Throwable) -> Unit): Job {
    return launch {
        val result = suspendCancellableCoroutine<R> { continuation ->
            continuation.invokeOnCompletion {
                if (continuation.isCancelled) {
                    NonCancellable.cancel()
                }
            }

            if (continuation.isActive) {
                try {
                    block(continuation)
                } catch (exp: Throwable) {
                    continuation.resumeWithException(exp)
                }
            }
        }

        launch (UI) {
            when (result) {
                is Throwable -> {
                    fail(result)
                }
                else -> {
                    success(result)
                }
            }
        }
    }
}
复制代码

使用方法也类似:

    processOnAsync<String>({ cont ->
        //耗时操作,注意这里并不会主动返回,
        //直到你代码调用cont.resumt(string) 或者 cont.resumeWithException(error throwable)
    }, success = {
        //成功时的处理代码
    }, fail = {
        //失败时的处理代码
    })
复制代码

三,仿concatMap
有了前面(二)的基础,也容易仿制一个简单的concatMap了。

fun <T, R> processAndConcatMap(list: List<T>,
                               block: (CancellableContinuation<R>, Int, T) -> Unit,
                               stepCtx: CoroutineContext = UI, step: (Int, R) -> Unit,
                               failCtx: CoroutineContext = UI, fail: (Int, Throwable) -> Unit,
                               doneCtx: CoroutineContext = UI, done: (List<T>) -> Unit = {}): Job {
    list.isNotEmpty() || return Job()
    return launch {
        var errorThrow = false
        list.forEachIndexed { index, value ->
            if (errorThrow) {
                return@forEachIndexed
            }

            val result = suspendCancellableCoroutine<R> { continuation ->
                continuation.invokeOnCompletion {
                    if (continuation.isCancelled) {
                        NonCancellable.cancel()
                    }
                }

                if (continuation.isActive) {
                    try {
                        block(continuation, index, value)
                    } catch (exp: Throwable) {
                        continuation.resumeWithException(exp)
                    }
                }
            }

            when (result) {
                is Throwable -> {
                    launch (failCtx) {
                        fail(index, result)
                    }
                }
                else -> {
                    launch (stepCtx) {
                        step(index, result)
                    }
                }
            }

            if (result is Throwable) {
                errorThrow = true
                return@forEachIndexed
            }
        }

        if (!errorThrow) {
            launch (doneCtx) {
                done(list)
            }
        }
    }
}
复制代码

注意入参中的stepCtx: CoroutineContext = UI这类参数。 这是用于协程切换的,可以控制step,fail,done这三个代码块分别运行于哪个线程中。
使用的时候呢,这样使用:

/*
dataList是List<SourceType>类型,需要在action中做一些耗时操作,
然后把SourceType转化为目标类型Pair<String, String>
*/
processWithConcatMap<SourceType, Pair<String, String>> (
        dataList,
        block = { cont, _, it ->
        
            //在这里进行SourceType转为Pair<String, String>类型的耗时操作
            
            if (/*normal*/true) {//如果转换成功就调用这里
                cont.resume(Pair("Left", "Right"))
            } else {//如果转换过程出错则调用这里
                cont.resumeWithException(Throwable())
            }
        },
        step = { _, _ ->
        },
        fail = { _, _ ->
        },
        done = {
        }
)
复制代码

注意这些方法,都设置了Job类型的返回值,这个Job返回值是为了方便取消协程用的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
其基础编译器(他们将其改为kompiler——开创了一系列以K字打头的用语——甚至连 contributors这类词他们也用改成了kontributors)可以被独立出来并嵌入到 Maven、Ant 或 Gradle 工具链中。这使得在 IDE 中开发的代码能够利用已有的机制来构建,从而尽可能的减少了在新环境中使用所受的干预,哪怕与那些没有安装 Kotlin 插件的开发人员一起合作项目也没有问题。 The IntelliJ Kotlin 插件扩展了 Java 编译器使得 Kotlin 代码能够得以编写、编译和调试。除此之外,关于基本的 Java 集合,已经有编写好的帮助函数,可以更顺畅地衔接将在 Java 8 中出现的集合扩展。 有两篇文章对 KotlinJava 以及 Kotlin 与 Scala 分别进行了比较,对各自特性和异同进行了对比。即便 Scala 可能还是更为强大些,Kotlin 还是尝试着提供比 Java 更好的函数、模式匹配、空指针预防和泛型。该语言同时也支持特征(traits)和模式匹配。 Kotlin 插件在当前版本的 IntelliJ 和 Eclipse 中均已能使用。 [4] Kotlin,类似 Xtend 一样,旨在提供一种更好的 Java 而非重建整个新平台。这两种语言都向下编译为字节码(虽然 Xtend 是首先转换成相应的 Java 代码,再让 Java 编译器完成繁重的工作),而且两者都引入了函数和扩展函数(在某个有限范围内静态地增加一个新方法到某个已有类型的能力)。Xtend 是基于 Eclipse 的,而 Kotlin 是基于 IntelliJ 的,两者都提供无界面构建。能够首先演变到其他 IDE 的语言有可能成为最后的赢家。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值