經過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,我以爲這兩個東西也仍是很類似的。

相關文章
相關標籤/搜索