Coroutines和Rxjava异步编程对比

原文地址:https://medium.com/@manuelvicnt/coroutines-and-rxjava-an-asynchronicity-comparison-part-1-asynchronous-programming-e726a925342a

这一系列的文章将会用来进行Coroutines和Rxjava在解决异步编程方面的对比。

案例一:为一个快速启动的App创建复杂的对象

如果希望自己的应用程序能够快速启动,那么处理创建对象的过程非常重要,如果对于复杂的对象创建发生在UI线程的话,将会引起丢帧的情况。
所以对于这种情况我们我们需要在后台线程中做这些操作。

RxJava

我们如何使用Rxjava来初始化我们想要的对象?

fun initializeObjectsAsync(): Completable{
  return Completable.create{ emitter -> 
    try{
      heavyInitialzation()
      if(!emitter?.isDisposed){
        emitter?.onComplete()
      }
    }catch(e:Exception){
      if (!emitter?.isDisposed) {
        emitter?.onError(e)
      }
    }
  }
}

正如你所见,我们创建了一个方法返回Completable对象,在方法内部,我们通过Completable.create创建了一个Completable,他将使用一个发射器(这个对象是可以被订阅的)。
执行完复杂的初始化后,我们将通知成功,如果有错误发生,我们将通知所发生的错误,这是因为发射器的类型是CompletableEmitter,而onComplete和onError是可用于将结果传递给订阅服务器的方法。

另一种方法是使用Completable.fromCallable()

fun initializeObjectsAsync(): Completable {
    return Completable.fromCallable({
            heavyInitialization()
    })
}

我们如何消费该方法呢?

Observables和Completables在Rxjava中都是冷冰冰的,这意味着我们只有订阅时,才会执行Completable.create中的代码,需要记住的是,每次订阅都会执行。
我们必须订阅我们在上面创建的initializeObjectsAsync函数中创建的Completable。

fun initializeObjects() {
    initializeObjectsAsync()
        .subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({
            // The initialization succeeded!
            // We can perform UI changes here 
        }, {
            // An Error occurred!
        })
}

我们如何告诉RxJava我们想要在后台线程中执行初始化操作?我们使用subscribeOn操作符来告诉RxJava,我们希望Completable.create中的代码能够在后台线程上执行。
当执行完毕时,我们需要对UI进行更新操作,我们可以使用observableOn操作符来告诉RxJava我们想在Android主线程中监听结果。

只有当你订阅Completable时,才会执行Completable.create中的代码

定义线程之后,我们需要启动订阅才能在完成时接收到通知,使用.subscribe方法来做到这一点,我们需要传递两个代码块,一个是接收成功的方法,一个是接收失败的方法。
如果想要上述代码被执行,我们需要创建一个Android Activity,例如,我们可以在onCreate方法中调用这个方法。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    initializeObjects()
}

Kotlin Coroutines

使用Coroutines的话会更简单,从概念上讲,协程和线程类似,我们可以编写在特定线程上运行的代码。

CoroutineBuilder是一个可以用来创建Coroutine的方法,运行一段代码,并以某种形式访问其结果,CoroutineBuilder的例子有:launch,async,runBlocking...

假设我们要像在onCreate方法中那样调用heavyInitialization方法,我们可以使用CoroutineBuilder启动创建一个Coroutine,并在要运行的代码块执行大量初始化的代码。

fun initializeObjects() {
    launch(CommonPool) {
        heavyInitialization()
    }
}

CommonPool类似于RxJava中的Schedulers.computation(),将会在后台线程中运行代码。
让我们模仿RxJava中构建的例子,我们想知道它什么时候完成初始化复杂对象和错误的处理。

fun initializeObjects() {
    launch(CommonPool) {
        try {
            heavyInitialization()
            // The initialization succeeded!
            withContext(UI) {
                // We can perform UI changes here
            }
        } catch (e: Exception) {
            // An Error occurred!
        }
    }
}

由于Coroutine中的代码被顺序执行,因此在初始化成功代码将接着初始化的代码执行。
和以前一样,我们可以将调用封装在try catch块中进行错误处理。

我们如何切换UI线程来通知UI更新,这里有一个方法withContext,使用另一个CoroutineContext来运行其中的代码块。

我们在示例中看到的CoroutineContext不是标准Kotlin Coroutines库中的一部分,由于它是Android专用的,因此可以在其他库中使用:org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version

示例二:在后台线程执行斐波那契数列

区别于在后台执行一些操作,我们也需要返回一个值,现在我们在用户点击按钮是计算斐波那契数列。

想象一下我们使用下面的代码来计算斐波那契数列:

private fun fib(n: Long): Long {        
    return if (n <= 1) n        
    else fib(n - 1) + fib(n - 2)    
}

我们如何在后台线程中计算他并且返回结果呢?

RxJava

这次我们使用Single来实现。

fun fibonacciAsync(number: Long): Single<Long> = 
    Single.create({ emitter ->
            val result = fib(number) 
            if (!emitter?.isDisposed) {       
                 emitter.onSuccess(result)
            }
})

你也可以使用fromCallback方法:

fun fibonacciAsync(number: Long): Single<Long> = 
    Single.fromCallable({
        return fib(number)
    })

我们把我们想要的数字作为该函数的参数传递,这也将在Single.create代码块中使用,例如,我们可以从EditText中获取该号码。

@OnClick(R.id.my_button)
fun onButtonClicked() { 
    fibonacciAsync(numberInputEditText.text.toString().toLong())
       .subscribeOn(Schedulers.computation())
       .observeOn(AndroidSchedulers.mainThread())
       .subscribe({ fibonacciNumber -> 
           //Update UI with the result 
           myTextView.text = fibonacciNumber
       },{
           // Error happened
       })
}

用户每次点击按钮,我们都将计算一个新的斐波那契数值,如果用户修改了Edittext中的值,结果也将会变得不同。

Kotlin Coroutines

这个示例将会和上面的一样简单,当用户点击按钮,我们就开启一个Coroutine来计算斐波那契数列。

@OnClick(R.id.my_button)
fun onButtonClicked(){
  launch(CommonPool) {
    val result = fibonacciAsync (
      numberInputEditText.text.toString().toLong()
    )
    withContext(UI){
      fibonacciResultTextView.text = result
    }
  }
}

下篇文章将介绍取消执行。
如何取消Observable和Coroutine。不要错过。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容