在可观察链中应用调度程序两次(使用compose)

时间:2016-04-25 13:40:49

标签: java android rx-java

我的应用中有多个网络电话。我喜欢使用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调用将覆盖&#34;覆盖&#34;前一个的行​​为。但实际上,看起来第一个observeOncompose主线程)的observeOn调用支配第二个compose调用(subscribeOn IO线程) 。一个明显的解决方案是拥有两个版本的networkCall1 - 一个应用调度程序而另一个不适用。但是,这会使我的代码非常冗长。

您知道更好的解决方案吗? 你能解释一下在一个可观察链中应用调度程序两次(使用compose)的行为吗?

编辑:我正在使用RxJava进行网络调用改造。

1 个答案:

答案 0 :(得分:8)

每个流只能使用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()呼叫,则可以。您必须在observeOn()方法中添加额外的chainedCalls()。每个流可以根据需要进行尽可能多的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());
}