通过Rxjava看Kotlin协程(一)
我在kotlin的协程使用过程中,其实发现了很多rxjava和协程之间很相似的地方。
如果把两个东西孤立起来学习,我觉得成本太高了。把相似的地方剥离出来理解,我觉得通过这种方式吧,可以把学习的成本大大的缩减下来。
下面给大家分享下我的一部分看法。
ObservableEmitter 和 suspendCoroutine
ObservableEmitter
想象一个水龙头和水流,这个管道就相当于Observable,从里面能放出水,ObservableEmitter 就相当于是水龙头,控制开关,而水龙头连接到管道就是 Observable.create()。
因为不知道为啥面试官喜欢问背压,那么我就用来Flowable举例子好了。
我至今没有碰到过任何关于背压的问题,有碰到朋友可以留言交流下
先说业务场景,有个页面要处理onActivityResult方法,但是我只有context实例,如果从activity一层层传递下来我又不开心,这个时候咋办。
object RxResult {
fun startForResult(activity: AppCompatActivity, requestCode: Int, targetActivity: Class): Flowable {
val fragment = EmptyFragment()
fragment.targetActivity = targetActivity
fragment.requestCode = requestCode
val flowable = Flowable.create(fragment, BackpressureStrategy.LATEST)
activity.supportFragmentManager.beginTransaction().add(fragment, "empty").commit() return flowable
}
}
class EmptyFragment : Fragment(), FlowableOnSubscribe {
private var emitter: FlowableEmitter? = null
var requestCode: Int = 1234
var targetActivity: Class? = null
override fun subscribe(emitter: FlowableEmitter) {
this.emitter = emitter
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
targetActivity?.apply {
val intent = Intent(context, targetActivity)
startActivityForResult(intent, requestCode)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
emitter?.onNext(resultCode == Activity.RESULT_OK)
}
}
上述的逻辑操作完全都是异步的,因为我们只知道了方法被调用到了,简单的说onActivityResult 函数触发了之后,我们调用了emmiter发射器的onNext 方法。
之后我们构建的Flowable就会接受到对应的回调了。这样我们就能把一个异步的操作,构建成一个流式的操作,对于调用方来说他们根本不关心我们内部是如何弯弯绕绕,他们只关心他们下游的流需要的后续操作就行了。
这个地方只是随手写的啊,可能会有bug的
suspendCoroutine 挂起函数
在异步编程中,回调是非常常见的写法,那么如何将回调转换为协程中的挂起函数呢?可以通过两个挂起函数suspendCoroutine{}
或suspendCancellableCoroutine{}。
这两个函数就是协程给我们提供的将异步回调写成挂起函数的方式。
private suspend inline fun loadLottie(url: String): LottieComposition? {
return suspendCancellableCoroutine { continuation ->
var resumed = false
val task = LottieCompositionFactory.fromUrl(getContext(), url, LottieHelper.getCacheKey(url))
task.addListener {
if (!resumed || continuation.isActive) {
continuation.resume(it)
resumed = true
}
}
task.addFailureListener {
continuation.resumeWithException(it)
}
}
}
还是用之前加载lottie的代码来介绍,其中CancellableContinuation就是和emitter一样的一个发射器, continuation.resume(it)这个方法我们可以类比成emitter的onNext方法,然后当协程接受到这个值的情况下,才会重新唤起下一步的执行。
总结
我个人看法,两者其实实现思路都是一样的,通过传输一个发射器给一个异步方法,然后由最后的结果发射回给调用方使用。
但是吧,如果现在让我选,我还是觉得协程真香,毕竟链式调用一旦过长的情况下,其实对于开发的能力要求就越高。而kotlin协程的写法起码看起来更像是顺序执行,可读性和可维护性其实对后续来说会更好一点。
如果各位觉得有帮助请帮忙转发点赞,辣鸡作者先赚点知名度。
预告
下次我应该会写下关于协程的dispatcher和rxjava的Schedulers,我觉得这两个东西也还是很相似的。
- 【Go 语言 时间相关操作 demo】
- redis AOF保存机制
- 用 TensorFlow 让你的机器人唱首原创给你听
- 不用synchronized块的话如何实现一个原子的i++?
- Oracle升级中的参数补充(r9笔记第2天)
- 【Go 语言,服务器模块】日志系统源码
- wait方法和sleep方法的区别
- Java面试系列10
- python django整理(三)页面基础(仿BBS)
- 高并发场景下的httpClient优化使用
- socket.io 相关:Example: A simple chat server(官方 实例)
- django整理(四)配置setting文件(CSS,JS,images,templates)路径
- idea 远程调试 tomcat web应用
- Java 中冷门的 synthetic 关键字原理解读
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 【Rust日报】2020-09-05 微软在c++静态分析工具实现了一些rust的安全规则
- 一起来玩玩WebGL
- 自研网关:多项目的swagger聚合功能
- Prometheus 如何做到“活学活用”,大牛总结的避坑指南
- 文档驱动 —— 表单组件(一):表单元素组件 优点缺点选择文本类的Inputcheck 多选value的类型问题
- Vue3.0源码结构分析
- 【每周一库】- cached - 缓存结构型、辅助函数记忆化
- meta生成器 —— 表单元素组件 meta表单代码meta的模板data变幻
- 不用写代码也能做表单 —— 加载meta即可 菜单表单加载json运行效果。ModelAbout
- 从0到1,手把手教你入门 etcd
- 数据结构:手把手带你了解 ”图“ 所有知识!(含DFS、BFS)
- 设计模式之单例模式
- AndroidStudio创建JNI 工程与调用
- Java 版植物大战僵尸思路和源码分享!
- 你好MyBatis 入门篇