为什么Observable不能在正确的线程上创建?

时间:2015-05-02 05:35:00

标签: android network-programming system.reactive rx-java rx-android

Observable observable = Observable.from(backToArray(downloadWebPage("URL")))
            .map(new Func1<String[], Pair<String[], String[]>>() {
                @Override
                public Pair<String[], String[]> call(String[] of) {
                    return new Pair<>(of,
                            backToArray(downloadWebPage("URL" + of[0])).get(0));
                }
            });

    observable.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(
            (new Observer<Pair>() {

                @Override
                public void onCompleted() {
                    // Update user interface if needed
                }

                @Override
                public void onError(Throwable t) {
                    // Update user interface to handle error
                }

                @Override
                public void onNext(Pair p) {
                   offices.add(new Office((String[]) p.first, (String[]) p.second));
                }
           }));

这运行,我得到android.os.NetworkOnMainThreadException。我希望它能运行一个由subscribeOn()方法设置的新线程。

3 个答案:

答案 0 :(得分:4)

假设实际网络请求发生在downloadWebPage()中,则错误位于代码的第一行: Observable observable = Observable.from(backToArray(downloadWebPage(“http://api.ataxcloudapp.com/v1/franchise/listing/?location=”+ ZIPCode))) 这相当于: String [] response = downloadWebPage(“http://api.ataxcloudapp.com/v1/franchise/listing/?location=”+ ZIPCode) Observable observable = Observable.from(backToArray(response)) 这应该清楚地表明,在创建任何Observable之前,在主线程上执行了downloadWebPage,更不用说订阅了。在这方面,RxJava无法改变Java的语义。 你可以做的是这样的事情(没有经过测试,但应该是正确的): Observable observable = Observable.create(new Observable.OnSubscribe&lt; String []&gt;(){         @覆盖         public void call(final Subscriber&lt;?super String []&gt; subscriber){             final String [] response = downloadWebPage(“http://api.ataxcloudapp.com/v1/franchise/listing/?location=”+ ZIPCode);             if(!subscriber.isUnsubscribed()){                 subscriber.onNext(backToArray(响应));                 subscriber.onCompleted();             }         } ) 现在,您的网络请求将在Observable订阅后发生,并将移动到您在subscribeOn()中指定的线程。

答案 1 :(得分:4)

您可以使用defer()downloadWebPage的调用推迟到您订阅可观察对象的时刻。

示例:

private Object slowBlockingMethod() { ... }

public Observable<Object> newMethod() {
    return Observable.defer(() -> Observable.just(slowBlockingMethod()));
}

Source

答案 2 :(得分:0)

你应该从

改变
**observable.subscribeOn(Schedulers.newThread())**

**observable.subscribeOn(Schedulers.io())**