RxJava - 如何在subscribe的lambda函数内启动异步网络调用?可观察

时间:2016-02-26 15:12:59

标签: android rx-java

以下是我的确切代码。请注意,在subscribe lambda函数中调用了foo(o)。这在Android中提供了严格的模式错误。现在我当然可以在这里分拆一个线程,但这是Rxjava的做事方式吗?我现在必须再考虑线程吗?想在这里知道我最好的选择。我怎么能这样做RxJava方式,以便代码的其他部分可以订阅将返回网络呼叫响应的新事件?基本上我通过异步响应将一种类型的事件MyObj转换为NetObj响应事件。

 public static final PublishSubject<MyObj> myObjSubject = PublishSubject.create();
  public static final Observable<MyObj> observable = myObjSubject.asObservable();


protected CompositeSubscription myCompositeSubs = new CompositeSubscription();

myCompositeSubs.add(
            observable.subscribe((MyObj o) -> {
                 // `. Update UI with MyObject and 
                 // 2. Kick off network call which will return JsonResponse type object which I would like to possibly process here and also publish to let others respond to it.
                 foo(o);  // $$$$$ million dollar question what if I am kicking off something long running here?
            }));


private void foo(MyObj o){

// long running request.  How to kick off long running from here? 
  JsonRespons resp = RestAdapter.makeQuest(o.url);
  // I want this JsonResponse object to be an even others can listen for. I don't want to just process it right here.

}

更新:只是为了澄清我想要做的是在类(Android Fragment)中监听数据事件MyObject。一旦我得到这个,我想做两件事,与MyObject同步更新UI,这是我想要消费的而不仅仅是转换。但我也想开始一个长期运行的请求。一个网络调用,它返回JsonObject响应。这可能会在它返回时处理相同的片段,或者我可能希望其他类能够监听此事件。所以我不是仅仅观察MyObject然后进行网络调用并获得响应。我需要做两个操作,一个同步另一个异步。

1 个答案:

答案 0 :(得分:3)

这是使用像flatMap这样的RxJava运算符的绝佳机会。如果您需要更多文档,请查看here,但flatMap允许您获取一个类型的Observable(您的Observable<MyObj>)并返回另一种类型的Observable(在这种情况下它可以如果您想知道您的长时间运行请求是否完成,请Observable<Void>Observable<Boolean>

看看这段代码:

Subscription sub = observable.flatMap((MyObj o) -> {
      // this will be run on your subscribeOn thread -- in background
      return Observable.just(foo(o));
    }).subscribe(aVoid -> {
      // we have completed both operations here, emissions will be 
      // on our observeOn() thread
    });

您的foo(MyObj)功能现在的结构为:

private Void foo(MyObj o) {
    // long running stuff
    return null;
}

返回类型Void而非void非常重要,这样我们才能使用flatMap运算符并返回Observable<Void>

所有长时间运行的foo()操作都将在您的subscribeOn()线程上运行,同时还有您的初始observable,一旦操作完成,它将向您发出Void项您subscribe()主题上的observeOn()(如果您想通知用户界面,这可以是Android中的主要主题)。

更新以允许在flatMap调用中使用UI:

注意:这假设第一个observable已在后台主题定义subscribeOn()observeOn()定义为AndroidSchedulers.mainThread()

Subscription sub = observable.flatMap((MyObj o) -> {
      // << do stuff with MyObj to UI HERE >> 
      return Observable.defer(() -> Observable.just(foo(o)))
          .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }).subscribe(aVoid -> {
      // foo() has completed, we're back on the UI thread
    });

如果你想对JsonResponse做一些事情,你会改变foo()函数来返回Void而不是foo(),那么你就可以使用Observable.create()的结果在UI线程上。

更新2:Observable.defer()更改为image2 = Image.open('./Images/Cache/Cache.png') finalimage = QtGui.QIcon() finalimage.addPixmap(QtGui.QPixmap(image2), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.FinalImage.setIcon(finalimage) self.FinalImage.setIconSize(QtCore.QSize(1300, 342)) 以使其更清晰。