Closed csshuai closed 6 years ago
Does this reproduce with Schedulers.computation()
?
There is an inherent race there because dispose() is called after onComplete() thus dependent on non-deterministic thread scheduling. If thread running create()
is also on the main thread, you'd see isDisposed()
true guaranteed in the follow-up task.
private Disposable mDisposable;
private Disposable mDisposable1;
public void test() {
Observable.create(new ObservableOnSubscribe
@Override public void onNext(@NonNull Boolean aBoolean) {
}
@Override public void onError(@NonNull Throwable e) {
Log.d("test", "onError");
}
@Override public void onComplete() {
Log.d("test", "onComplete");
getHandler().postDelayed(new Runnable() {
@Override public void run() {
Log.d("test1", "isDisposed: " + mDisposable.isDisposed());
}
}, 1000);
}
});
}
public void test1() {
Observable.create(new ObservableOnSubscribe
@Override public void onNext(@NonNull Boolean aBoolean) {
}
@Override public void onError(@NonNull Throwable e) {
Log.d("test1", "onError");
}
@Override public void onComplete() {
Log.d("test1", "onComplete");
getHandler().postDelayed(new Runnable() {
@Override public void run() {
Log.d("test1", "isDisposed: " + mDisposable1.isDisposed());
}
}, 1000);
}
});
} Duplicar de #366
This issue is nothing to do with RxAndroid. Actually, if you observe on any other schedulers except Schedulers.trampoline() will lead to the same result. The onComplete method of ObservableEmitter looks like this:
static final class CreateEmitter<T> extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
....
@Override
public void onComplete() {
if (!isDisposed()) {
try {
observer.onComplete();
} finally {
dispose();
}
}
}
....
}
It will dispose itself after onComplete was called. And Observer.onSubscribe(CreateEmitter) was called before ObservableOnSubscribe.subscribe. If there is no other operation, CreateEmitter is the Disposable you get from your onSubscribe.
But when you chain your Observable with observeOn, the Disposable you get changed. It will return a new Observable to downstream and when the subscribe method was called it will make the origin Observable subscribing its own Observer.In this case it subscribes ObserveOnObserver:
static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
implements Observer<T>, Runnable {
...
public void onSubscribe(Disposable s) {
actual.onSubscribe(this);
}
...
@Override
public void onComplete() {
if (done) {
return;
}
done = true;
schedule();
}
...
boolean checkTerminated(boolean d, boolean empty, Observer<? super T> a) {
...
if(empty) {
if (e != null) {
a.onError(e);
} else {
a.onComplete();
}
worker.dispose();
return true;
}
...
}
}
When the onComplete was called the ObserveOnObserver does not dispose itself. But at now, the ObservableEmitter has been disposed. So the connection between upstream and downstream is cut down. Also by reading the source code you can find that if your manually dispose the Disposable it will dispose up to the first Disposable to make the ObservableEmitter stop emitting.
So I suppose the author intended to do so, cause there is really no need to change the state of all the Disposable downstream.
Other
Can add a method in AndroidSchedulers?