经过Rxjava看Kotlin协程(一)

我在kotlin的协程使用过程当中,其实发现了不少rxjava和协程之间很类似的地方。java

若是把两个东西孤立起来学习,我以为成本过高了。把类似的地方剥离出来理解,我以为经过这种方式吧,能够把学习的成本大大的缩减下来。面试

下面给你们分享下个人一部分见解。编程

ObservableEmitter 和 suspendCoroutine

ObservableEmitter 

想象一个水龙头和水流,这个管道就至关于Observable,从里面能放出水,ObservableEmitter 就至关因而水龙头,控制开关,而水龙头链接到管道就是 Observable.create()。

由于不知道为啥面试官喜欢问背压,那么我就用来Flowable举例子好了。bash

我至今没有碰到过任何关于背压的问题,有碰到朋友能够留言交流下

先说业务场景,有个页面要处理onActivityResult方法,可是我只有context实例,若是从activity一层层传递下来我又不开心,这个时候咋办。app

object RxResult {  
  fun startForResult(activity: AppCompatActivity, requestCode: Int, targetActivity: Class<out Activity>): Flowable<Boolean> {    
    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<Boolean> {   
     private var emitter: FlowableEmitter<Boolean>? = null    
    var requestCode: Int = 1234    
    var targetActivity: Class<out Activity>? = null    

    override fun subscribe(emitter: FlowableEmitter<Boolean>) { 
          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就会接受到对应的回调了。这样咱们就能把一个异步的操做,构建成一个流式的操做,对于调用方来讲他们根本不关心咱们内部是如何弯弯绕绕,他们只关心他们下游的流须要的后续操做就好了。ide

这个地方只是随手写的啊,可能会有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,我以为这两个东西也仍是很类似的。

相关文章
相关标签/搜索