目标
首先,定义好异步结果泛化类型AsyncResult,此处会用到Kotlin泛型编程基础知识:
sealed class AsyncResultdata class AsyncSuccess (val data: T?) : AsyncResult ()data class AsyncError(val error: String?) : AsyncResult ()inline fun AsyncResult .onSuccess(action: (T?) -> Unit): AsyncResult { if (this is AsyncSuccess) action(data) return this}inline fun AsyncResult .onError(action: (String) -> Unit) { if (this is AsyncError && error != null) action(error)}复制代码
基于此AsyncResult和Kotlin协程suspend关键字,可以定义任意异步操作(网络请求,数据库操作等)如下:
suspend fun demoAction(): AsyncResult
> { //请暂时忽略实现方法 }复制代码
接下来好戏登场,UI部分的代码:
launch { demoAction() .onSuccess { Toast.makeText(this@MainActivity, "Successfully Fetched ${it?.size} Items", Toast.LENGTH_LONG) .show() } .onError { Toast.makeText(this@MainActivity, "Failed!! -- $it", Toast.LENGTH_LONG).show() } } 复制代码
非常优雅有木有?!
具体操作(实现)
展示过了魔术效果, 我们来揭秘下几处关键手法:
- sealed class 描述了受限的类继承结构,即限定了此类实例只能是有限的几种类型。 AsyncSuccess和AsyncError则是AsyncResult的派生类而已。
- onSuccess和oError是AsyncResult的扩展方法(Kotlin可以给已知的任何 class 类添加函数), 其中onSuccess还返回了自身对象,以便链式调用。
- onSuccess和onError均接受唯一一个Lambda参数, 从而可以实现形式上
onSuccess{}.onError{}
的写法。