Rxandroid What's the difference between SubscribeOn and ObserveOn

后端 未结 5 2013
逝去的感伤
逝去的感伤 2020-12-23 09:09

I am just learning Rx-java and Rxandroid2 and I am just confused what is the major difference between in SubscribeOn and ObserveOn.

5条回答
  •  离开以前
    2020-12-23 09:47

    This answer is nothing new, I just want to clarify a little bit more.

    1. Let's assume that we have two threads.

       val pool1 = Executors.newCachedThreadPool { runnable -> Thread(runnable, "Thread 1") }
       val pool2 = Executors.newCachedThreadPool { runnable -> Thread(runnable, "Thread 2") }
      

    1. As the answers described, observeOn will set Downstream, and subscribeOn will set Upstream. But what if both of them was used? For check this, I added logs line by line.

      Observable.just("what if use both")
       .doOnSubscribe { Log.d("Thread", "both, doOnSubscribe A " + Thread.currentThread().name) }
       .doOnNext { Log.d("Thread", "both, doOnNext A " + Thread.currentThread().name) }
       .map {
           Log.d("Thread", "both, map A " + Thread.currentThread().name)
           it + " A"
       }
      
       // observeOn
       .observeOn(Schedulers.from(pool1)) 
      
       .doOnSubscribe { Log.d("Thread", "both, doOnSubscribe B " + Thread.currentThread().name) }
       .doOnNext { Log.d("Thread", "both, doOnNext B " + Thread.currentThread().name) }
       .map {
           Log.d("Thread", "both, map B " + Thread.currentThread().name)
           it + " B"
       }
      
       // subscribeOn
       .subscribeOn(Schedulers.from(pool2)) 
      
       .doOnSubscribe { Log.d("Thread", "both, doOnSubscribe C " + Thread.currentThread().name) }
       .doOnNext { Log.d("Thread", "both, doOnNext C " + Thread.currentThread().name) }
       .map {
          Log.d("Thread", "both, map C " + Thread.currentThread().name)
          it + " C"
        }
      
       // observeOn main
       .observeOn(AndroidSchedulers.mainThread())
       .doOnNext { Log.d("Thread", "main " + Thread.currentThread().name) }
       .subscribe(
           { result -> Log.d("Thread", "main subscribe " + Thread.currentThread().name)}
           , { error -> {} }
           )
      

    The result is:

    both, doOnSubscribe C main
    both, doOnSubscribe A Thread 2
    both, doOnSubscribe B Thread 2
    
    both, doOnNext A Thread 2
    both, map A Thread 2
    
    both, doOnNext B Thread 1
    both, map B Thread 1
    
    both, doOnNext C Thread 1
    both, map C Thread 1
    
    main main
    main subscribe main
    result: what if use both A B C
    

    As you can see, doOnSubscribe called first, from bottom to top. That means subscribe has priority over other operators, so the first thread which handles first code was Thread 2.

    And then other operators was called, line by line. After observeOn, thread was changed to Thread 1. Then, just before calling subscribe, observeOn was called again, for change thread to main thread. (Don't care about AndroidSchedulers, it is just a kind of scheduler)

    TL;DR;

    • First path, subscribeOn called first, from bottom to top.
    • Second path, observeOn called, from top to bottom, along with other codes.
    • Behavior was same on both RxJava2 and RxJava3

提交回复
热议问题