【发布时间】:2015-05-27 12:28:45
【问题描述】:
我有一个Button,我从中创建了一个Observable<OnClickEvent>。
单击按钮时,我希望从网络中获取文件,但遇到了有关网络和线程的问题。
这个例子抛出android.os.NetworkOnMainThreadException:
Observable<OnClickEvent> networkButtonObservable = ViewObservable.clicks(testNetworkButton);
networkButtonObservable
.map(new Func1<OnClickEvent, List<String>>() {
@Override
public List<String> call(OnClickEvent onClickEvent) {
return TestAPI.getTestService().fetchTestResponse();
}
}
)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Object>() {
@Override
public void call(Object o) {Log.w("Final result: " + o);
}
}
);
所以我从另一个线程尝试。
以下抛出rx.exceptions.OnErrorNotImplementedException: Observers must subscribe from the main UI thread, but was Thread[RxNewThreadScheduler-1,5,main]:
networkButtonObservable
.subscribeOn(Schedulers.newThread())
.map(new Func1<OnClickEvent, List<String>>() {
@Override
public List<String> call(OnClickEvent onClickEvent) {
return TestAPI.getTestService().fetchTestResponse();
}
}
)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Object>() {
@Override
public void call(Object o) {Log.w("Final result: " + o);
}
}
);
好的.. 现在我尝试在开头使用.debounce():
networkButtonObservable
.debounce(10, TimeUnit.MILLISECONDS)
.map(new Func1<OnClickEvent, List<String>>() {
@Override
public List<String> call(OnClickEvent onClickEvent) {
return TestAPI.getTestService().fetchTestResponse();
}
}
)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Object>() {
@Override
public void call(Object o) {Log.w("Final result: " + o);
}
}
);
这成功了。
显然我不喜欢在我的代码中添加延迟,所以我试图找出线程方面发生了什么。为什么第一个示例不在后台线程中执行.map() 内的代码?
或者我在这里错过了什么?
--- 更新
我将我的 TestAPI 更改为返回一个 Observable,并将对 networkButtonObservable 的第一次调用更改为 .flatMap()。这也可以正常工作。但是我还是不知道为什么原来使用.map()的方式会失败。
networkButtonObservable
.flatMap(new Func1<OnClickEvent, Observable<?>>() {
@Override
public Observable<?> call(OnClickEvent onClickEvent) {
return TestAPI.getTestService().fetchTestResponseObservable();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Object>() {
@Override
public void call(Object o) {Log.w("Final result: " + o);
}
}
);
【问题讨论】:
-
正如错误所说,您无法在 UI 线程中运行网络操作。
-
哪一行抛出这个异常:
Observers must subscribe from the main UI thread, but was ...?我认为您在 UI 线程的另一个线程中订阅了您的 Observable。 (但我不舒尔) -
.subscribeOn(Schedulers.io())必须在你的地图之后,因为地图中的函数在订阅时被调用
标签: android multithreading rx-java rx-android