我使用RxParse来解析查询的异步加载但是当我使用subscribeOn(Schedulers.io())订阅我的observable时,我的onCompleted方法永远不会在主线程上调用。而不是这个,我的onCompleted方法在工作线程池内调用。如果我使用observeOn(AndroidSchedulers.mainThread),一切都会工作,但我的onNextMethod也将在主线程上调用,我不想要它。
我的代码有问题吗?
我的代码有什么问题吗?
ParseObservable.find(myQuery)
.map(myMapFunc())
.subscribeOn(AndroidSchedulers.handlerThread(new Handler()))
.subscribe(
new Subscriber<MyObj>() {
@Override
public void onError(Throwable e) {
Log.e("error","error",e);
}
@Override
public void onNext(T t) {
// ... worker thread (but here is ok)
}
public void onCompleted() {
// ... worker thread again instead of mainThread
}
}
)
);
答案 0 :(得分:9)
首先,您需要了解subscribeOn()
和observeOn()
之间的区别。这两个完全不同的运算符会影响Rx链的不同部分。
subscribeOn()
指定Observable的工作位置。它不会影响onNext()
,onError()
和onComplete()
执行的位置。
observeOn()
指定回调(例如onNext()
)的执行位置。它不会影响Observable的工作位置。
所有回调都将在同一个线程上发生。您不能指定某个回调在一个线程上发生,而某些回调在另一个线程上发生,通过任何RxJava API。如果这是你想要的行为,你将不得不在你的回调中自己实现它。
答案 1 :(得分:6)
不幸的是,订阅位于所有方法的同一个主题中(onNext
,onError
和onCompleted
但是您可以在Schedulers.io()
和onNext(T t)
方法内部观察,创建一个新的Observable
来监听MainThread
,如下所示:
ParseObservable.find(myQuery)
.map(myMapFunc())
.subscribeOn(Schedulers.io())
.subscribe(
new Subscriber<MyObj>() {
@Override
public void onError(Throwable e) {
Log.e("error","error",e);
}
@Override
public void onNext(T t) {
Observable.just(t)
.observeOn(AndroidSchedulers.mainThread())
.subscribe((t) -> {
// do something in MainThread
})
}
public void onCompleted() {
// ... worker thread again instead of mainThread
}
}
)
);
我希望它有所帮助!
答案 2 :(得分:2)
我建议使用&#34;副作用&#34;这种情况下的运营商。在我看来,比使用嵌套的observable更优雅的解决方案:
ParseObservable.find(myQuery)
.map(myMapFunc())
.subscribeOn(AndroidSchedulers.handlerThread(new Handler()))
.doOnCompleted(() -> onCompleteAction())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(value -> onNext(value))
.subscribe();
答案 3 :(得分:2)
不建议在订阅中订阅。
subscribeOn
确定Observable链在观察者订阅时开始的位置。
observeOn
可以在整个可观察链中的不同点(多次,如果需要)使用在线程之间传递控制。 (您可以通过检查是否在主线程内或每个块中都没有来验证这一点。)
ParseObservable.find(myQuery)
.map(myMapFunc())
// Added this:
.doOnNext(obj -> {
// NOTE: This will happen on your `subscribeOn` scheduler
// Do something with `obj` here while on worker thread
}
.subscribeOn(AndroidSchedulers.handlerThread(new Handler()))
// Added this:
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<>() {
next -> {
// NOTE: This will happen on the main thread
},
error -> {
Log.e("error","error",e);
// NOTE: This will happen on the main thread
},
() -> {
// NOTE: This will happen on the main thread
}
});