RxJava - 何时使用带有create方法的Observable

时间:2016-03-22 21:04:22

标签: java multithreading rx-java reactive-programming

我正在阅读教程:

http://code.tutsplus.com/tutorials/getting-started-with-reactivex-on-android--cms-24387

特别是RxAndroid,但它与RxJava几乎相同。我不确定我是否完全理解这个概念。

下面我编写了一个方法,然后是一个示例用法。

我的问题是:这是实现我的函数的正确方法,以便我可以异步地在其他线程上运行它们吗?实际上,它们只会返回一个运行真实代码的已创建Observable,并处理错误和所有这些内容。

或者这是错的,那么我想知道正确的方法。

Observable<String> googleSomething(String text){
    return Observable.create(new Observable(){
        @Override
        public void call(Subscriber<? super String> subscriber) {
             try {
                String data = fetchData(text); // some normal method
                subscriber.onNext(data); // Emit the contents of the URL
                subscriber.onCompleted(); // Nothing more to emit
            } catch(Exception e) {
                subscriber.onError(e); // In case there are network errors
            }
        }
    });
}

googleSomething("hello world").subscribeOn(Schedulers.io()).observeOn(Schedulers.immediate()).subscribe(...)

还使用Schedulers.immediate()来执行当前线程上的订户代码?它说“创建并返回一个在当前线程上立即执行工作的调度程序。”在javadoc,但我不确定。

4 个答案:

答案 0 :(得分:7)

除非您更有经验并需要自定义运算符或想要桥接基于旧版addListener / removeListener的API,否则不应以create开头。 StackOverflow上有几个问题使用create并且是麻烦的来源。

我更喜欢fromCallable,它让您生成单个值或抛出异常,因此不需要那些冗长的defer + just来源。

Schedulers.immediate()立即在调用者的线程上执行其任务,该线程是示例中的io()线程,而不是主线程。目前,不支持将计算移回 Java 主线程,因为它需要阻止蹦床,并且通常是一个坏主意。

答案 1 :(得分:2)

你几乎不应该使用create(),尤其不是初学者。有更简单的方法来创建可观察对象,create()很难正确实现。

大多数情况下,您可以使用create()轻松绕过defer()。例如,在这种情况下你会做:

Observable<String> googleSomething(String text) {
  return Observable.defer(new Func0<Observable<String>>() {
    @Override
    public Observable<String> call() {
      try {
        return Observable.just(fetchData(text));
      } catch (IOException e) {
        return Observable.error(e);
      }
    }
  });
}

如果您没有使用已检查的异常,那么您甚至可以摆脱try-catch。 RxJava会自动将任何RuntimeException转发给订阅者的onError()部分。

答案 2 :(得分:1)

您可以通过Observable.create(new OnSubscribe {})方法创建Observable:

  • 查看defer()运算符,它允许您返回例如Observable.just()和Observable.error(),这样您就不需要直接触及订阅者了
  • 首选使用SyncOnSubscribe / AsyncOnSubscribe处理背压

Schedulers.immediate()将在它已经存在的线程上保持Observable处理 - 所以在你的情况下它将是Schedulers.io线程之一

答案 3 :(得分:1)

您的代码对我来说很好。如果你不确定是否在另一个线程上运行。您可以在致电.subscribe()后立即打印一些内容并查看输出的顺序。

googleSomething("hello world").subscribeOn(Schedulers.io()).observeOn(Schedulers.immediate()).subscribe(...) 
System.out.println("This should be printed first");

尝试在fetchData()内模拟长时间运行的操作,然后立即打印其他内容。因为.subscribe()是非阻塞的,所以应该首先打印#34;事实上,将首先打印。

或者,您可以使用。

打印当前线程
Thread.currentThread().getName()

在您的observable内外使用它,输出应该不同。