当前位置: 首页 > 知识库问答 >
问题:

Rxandroid SubscribeOn和ObserveOn有什么区别

乌翰学
2023-03-14

我只是在学习Rx-java和Rxandroid2,我只是很困惑SubscribeOn和AnalyeOn之间的主要区别是什么。

共有3个答案

江凯风
2023-03-14
  • 使用observeOn为回调设置线程“进一步向下(在它下面)”,例如doOnNext中的代码块或map中的代码块

让我们通过一个示例来了解这个主题:我们想找到字符串“user1032613”的长度。对于计算机来说,这不是一项容易的任务,因此我们在后台线程中执行密集的计算是很自然的,以避免冻结应用程序。

我们可以任意多次调用observeOn,它控制下面的所有回调将运行哪个线程。它很容易使用,并且正如您所期望的那样工作。

例如,我们将在主UI线程上显示进度条,然后在另一个线程中执行强化/阻止操作,然后返回主UI线程以更新结果:

    Observable.just("user1032613")

            .observeOn(mainThread) // set thread for operation 1
            .doOnNext {
                /* operation 1 */
                print("display progress bar")
                progressBar.visibility = View.VISIBLE
            }

            .observeOn(backThread) // set thread for operation 2 and 3
            .map {
                /* operation 2 */
                print("calculating")
                Thread.sleep(5000)
                it.length
            }

            .doOnNext {
                /* operation 3 */
                print("finished calculating")
            }

            .observeOn(mainThread) // set thread for operation 4
            .doOnNext {
                /* operation 4 */
                print("hide progress bar and display result")
                progressBar.visibility = View.GONE
                resultTextView.text = "There're $it characters!"
            }

            .subscribe()

在上面的示例中,操作1*/在主线程中运行,因为我们在其正上方的行上使用observeOn(主线程)对其进行设置;然后我们通过再次调用observeOn切换到backThread,因此操作2*/将在那里运行。因为我们在链接操作3之前没有更改它,所以它也会在后线程中运行,就像操作2一样;最后,我们再次调用observeOn(主线程),以确保操作4从主线程更新UI。

所以我们已经了解了观测为后续回调设置线程。我们还缺少什么?好吧,观测本身,以及它的方法,如Just()create()订阅()等,也是需要执行的代码。这就是对象沿流传递的方式。我们使用订阅为与观测本身相关的代码设置线程。

如果我们删除所有回调(由前面讨论的观察控制),我们将剩下“骨架代码”,默认情况下,它将在编写代码的任何线程上运行(可能是主线程):

    Observable.just("user1032613")
            .observeOn(mainThread)
            .doOnNext {
            }
            .observeOn(backThread)
            .map {
            }
            .doOnNext {
            }
            .observeOn(mainThread)
            .doOnNext {
            }
            .subscribe()

如果我们对这个在主线程上运行的空骨架代码不满意,我们可以使用subbeOn来更改它。例如,也许第一行Observable.just("user1032613")并不像从我的用户名创建一个流那么简单——也许它是来自Internet的字符串,或者您正在使用doOnSubscribe进行其他一些密集操作。在这种情况下,您可以调用subbeOn(backThread)将一些代码放在另一个线程中。

在写这个答案的时候,有一些误解说“只调用一次”、“位置不重要”、“如果多次调用,只有第一次才算数”。经过大量的研究和实验,事实证明subbeOn可以有效地多次调用。

因为观察使用Builder Pattern(“一个接一个链接方法”的花哨名称),所以订阅以相反的顺序应用。因此,此方法将代码的线程设置在其上方,与观察正好相反。

我们可以使用doOnSubscribe方法对此进行实验。此方法在订阅事件上触发,并在subbeOn设置的线程上运行:

    Observable.just("user1032613")
            .doOnSubscribe {
                print("#3 running on main thread")
            }
            .subscribeOn(mainThread) // set thread for #3 and just()
            .doOnNext {
            }
            .map {
            }
            .doOnSubscribe {
                print("#2 running on back thread")
            }
            .doOnNext {
            }
            .subscribeOn(backThread) // set thread for #2 above
            .doOnNext {
            }
            .doOnSubscribe {
                print("#1 running on default thread")
            }
            .subscribe()

如果您自下而上阅读上面的示例,可能更容易遵循逻辑,就像Builder模式如何执行代码一样。

在本例中,第一行<代码>可见。只是(“user1032613”)与打印(“#3”)在同一线程中运行,因为它们之间没有更多的订阅。这给那些只关心内部代码的人造成了“只有第一次调用才重要”的错觉。一旦你开始做更多的事情,它很快就会崩溃。

为简洁起见,示例中的线程和print()函数定义如下:

val mainThread = AndroidSchedulers.mainThread()
val backThread = Schedulers.computation()
private fun print(msg: String) = Log.i("", "${Thread.currentThread().name}: $msg")
司寇星海
2023-03-14

如果你发现上面的答案充满了行话:

tl;博士

 Observable.just("Some string")                 
           .map(str -> str.length())              
           .observeOn(Schedulers.computation())   
           .map(length -> 2 * length)   
           .observeOn(AndroidSchedulers.mainThread())
           .subscribeOn(Schedulers.io())
           .subscribe(---)

观察可观察到的。。。在IO线程中执行映射功能(因为我们正在订阅该线程)。。。现在切换到计算线程并执行映射(长度-

无论如何

observeOn()只需将所有操作符的线程进一步更改为下游。人们通常会有这样的误解,认为observeOn也起着上游的作用,但事实并非如此。

下面的例子会更好地解释它...

Observable.just("Some string")                  // UI
       .map(str -> str.length())               // UI
       .observeOn(Schedulers.computation())   // Changing the thread
       .map(length -> 2 * length)            // Computation
       .subscribe(---)

subscribeOn()仅影响当Observable将被订阅时将要使用的线程,并且它将停留在它的下游。

Observable.just("Some String")              // Computation
  .map(str -> str.length())                // Computation
  .map(length -> 2 * length)              // Computation
  .subscribeOn(Schedulers.computation()) // -- changing the thread
  .subscribe(number -> Log.d("", "Number " + number));// Computation

位置无关紧要(subbeOn()

为什么?因为它只影响订阅时间。

服从订阅者联系的方法

-

创建主体中指定的所有工作都将在subscribeOn中指定的线程上运行。

另一个例子:Observable.justObservable.fromObservable.range

注意:所有这些方法都接受值,所以不要使用阻塞方法来创建这些值,因为subscribeOn不会影响它。

如果要使用阻塞函数,请使用

<代码>可见。延迟(()-

重要事实:

subscribeOn不适用于主题

多个订阅

如果流中有多个subscribeOn实例,则只有第一个实例具有实际效果。

订阅

人们认为subbeOnObservable.subscribe有关系,但并没有什么特别的关系,它只影响订阅阶段。

资料来源:托梅克·波兰斯基(中等)

丌官炎彬
2023-03-14

SubscribeOn指定可观察对象将在其上运行的调度程序。ObserveOn指定观察者将在其上观察此可观察对象的计划程序。

因此,基本上SubscribeOn主要是在后台线程上订阅(执行)(您不希望在等待可观察到的结果时阻止UI线程),并且在ObserveOn中,您希望在主线程上观察结果。。。

如果您熟悉AsyncTask,那么SubscribeOn类似于doInBackground方法,而ObserveOn类似于onPostExecute。。。

 类似资料:
  • 问题内容: 我只是在学习Rx-java和Rxandroid2,我只是对SubscribeOn和ObserveOn之间的主要区别感到困惑。 问题答案: SubscribeOn指定将在其上运行Observable的调度程序。ObserveOn指定调度程序,观察者将在该调度程序上观察此Observable。 因此基本上,SubscribeOn主要是在后台线程上预订(执行)(您不想在等待可观察对象时阻塞U

  • 问题内容: 两者都意味着空间,但是有什么区别吗? 问题答案: 一个是不间断空间,另一个是常规空间。不间断的空格表示该行不应在该点处换行,就像它不会在一个单词的中间换行一样。 此外,正如斯文德(Svend)在其评论中指出的那样,不间断的空间不会崩溃。

  • 本文向大家介绍<%# %> 和 <% %> 有什么区别?相关面试题,主要包含被问及<%# %> 和 <% %> 有什么区别?时的应答技巧和注意事项,需要的朋友参考一下 答:<%# %>表示绑定的数据源 <%%>是服务器端代码块  

  • 问题内容: 以下代码之间有什么区别: 和 Python建议采用一种做事方式,但有时似乎不止一种。 问题答案: 一个是函数调用,一个是文字: 使用第二种形式。它更具Python风格,并且可能更快(因为它不涉及加载和调用单独的函数)。

  • 发展至今(2020 年 6 月份),GCC 编译器已经更新至 10.1.0 版本,其功能也由最初仅能编译 C 语言,扩增至可以编译多种编程语言,其中就包括 C++ 。 除此之外,当下的 GCC 编译器还支持编译 Go、Objective-C,Objective-C ++,Fortran,Ada,D 和 BRIG(HSAIL)等程序,甚至于 GCC 6 以及之前的版本还支持编译 Java 程序。但本

  • 问题内容: 比较PMD和CheckStyle有一个问题。但是,我找不到关于PMD和FindBugs之间差异/相似性的详尽分类。我相信一个关键的区别是PMD适用于源代码,而FindBugs适用于编译的字节码文件。但是就功能而言,这应该是一个选择,还是两者相辅相成? 问题答案: 我同时使用。我认为他们是相辅相成的。 正如您所说,PMD在源代码上工作,因此会发现诸如以下问题:违反命名约定,缺少花括号,放