2016-04-25 48 views
5

我的应用程序中有多个网络调用。我喜欢使用compose运营商,该变压器运行在IO线程的网络请求:在可观察链中应用调度器两次(使用撰写)

public static <T> Transformer<T, T> runOnIoThread() 
{ 
    return tObservable -> tObservable.subscribeOn(Schedulers.io()) 
     .observeOn(AndroidSchedulers.mainThread()); 
} 

这似乎还有很长的工作,因为我只有单一的网络电话。但是,如果我像下面的例子那样链接它们,我会得到Android的NetworkInMainThreadException。

public Observable<String> networkCall1() 
{ 
    return <NETWORK_CALL_1()> 
      .compose(runOnIoThread()); 
} 

public Observable<String> networkCall2(String input) 
{ 
    return <NETWORK_CALL_2(input)> 
      .compose(runOnIoThread()); 
} 

public Observable<String> chainedCalls() 
{ 
    return networkCall1() 
      .flatMap(result1 -> networkCall2(result1)); 
} 

我的想法之前是compose在调用之前应用到整个可观测链,而后来compose通话将“覆盖”前一个行为。但实际上,它看起来像observeOn调用的第一个composeobserveOn主线程)主宰第二个compose调用(subscribeOn的IO线程)。一个明显的解决方案是有networkCall1两个版本 - 一个应用调度程序,另一个不应用调度程序。但是,这会让我的代码非常冗长。

你知道更好的解决方案吗? 您能否解释在可观察链中应用调度程序两次(与撰写)的行为?

编辑︰我正在使用RxJava翻新为我的网络调用。

回答

7

每个流只能使用subscribeOn()。如果你再次使用它,它不会做任何事情。因此,当你的两种方法串联起来运行:

observeOn(AndroidSchedulers.mainThread())

其在主线程切换操作。之后,它会留在那里,因为下一个subscribeOn()被有效地忽略。

我会建议你实际上用你的撰写方法过分复杂。只需添加

subscribeOn(Schedulers.io())

到这两个网络的呼叫,然后使用

observeOn(AndroidSchedulers.mainThread())

你要处理的主线程的结果之前。你最终的东西,如:

public Observable<String> networkCall1() 
{ 
    return <NETWORK_CALL_1()> 
      .subscribeOn(Schedulers.io); 
} 

public Observable<String> networkCall2(String input) 
{ 
    return <NETWORK_CALL_2(input)> 
      .subscribeOn(Schedulers.io); 
} 

public Observable<String> chainedCalls() 
{ 
    return networkCall1() 
      .flatMap(result1 -> networkCall2(result1)) 
      .observeOn(AndroidSchedulers.mainThread()); 
} 

编辑

如果你真的想对你可以在各个网络调用方法的调用observeOn()。您必须为您的chainedCalls()方法增加额外的observeOn()。您可以为每个流设置尽可能多的observeOn()调用。它会是这样的:

public Observable<String> networkCall1() 
{ 
    return <NETWORK_CALL_1()> 
      .subscribeOn(Schedulers.io) 
      .observeOn(AndroidSchedulers.mainThread()); 
} 

public Observable<String> networkCall2(String input) 
{ 
    return <NETWORK_CALL_2(input)> 
      .subscribeOn(Schedulers.io) 
      .observeOn(AndroidSchedulers.mainThread()); 
} 

public Observable<String> chainedCalls() 
{ 
    return networkCall1() 
      .observeOn(Schedulers.io) 
      .flatMap(result1 -> networkCall2(result1)) 
      .observeOn(AndroidSchedulers.mainThread()); 
} 
+0

嗨Jahnold!谢谢!你的解释帮助我更好地理解了subscribeOn,observeOn和撰写。 由于我的方法将成为图书馆的一部分,因此我希望尽可能简单地拨打电话(即省略observeOn电话)。杰克华顿写道[这里](http:// stackoverflow。com/a/21010181/2011622)关于使用RxJava进行Retrofit时,它在IO /后台线程中执行调用,并且observeOn位于调用者线程上。尽管如此,链接两个翻新电话仍然是可能的。所以一定有办法做到这一点,对吧? –

+0

我已经更新了答案,以显示如果您真的希望它们全部成为呼叫的一部分,您可以如何使用额外的'observeOn'。 – Jahnold

+1

感谢您的详细介绍!所以虽然'subscribeOn'只能在流中使用一次'observeOn'可以多次使用切换到不同的线程。我无法在文档中找到这些信息。你怎么知道的?你有参考吗? –