问题
I am trying to find a way to execute observable until some condition is met.
Consider the following example:
myDelayedObservable = createListenerObserver();
public Observable<Boolean> createListenerObserver() {
// The part I am looking for
}
ViewTreeObserver.OnGlobalLayoutListener listenerLayout = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
myDelayedObservable.onCompleted();
getTargetView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
};
public void performMultipleRequests() {
Observable<Boolean> longRunningTask = Observable.zip(oneRequest, anotherRequest, myDelayedObservable,...);
}
So the idea is to run multiple requests, for instance a download request, together with myDelayedObservable
using zip
, so longRunningTask
completes only when all requests plus listener (in my case view finished layout) are completed.
But the problem is, I cannot find the right way to create my Observable for listener. It is like a barrier, so pseudo code
while(!viewIsLaidOut) {
// just wait
}
observable.complete();
// After that `longRunningTask` should be completed
Please suggest the right way to achieve this, I have thought about Future
, Callable
but this seems to not be the best solution to me.
回答1:
1) You need to map
all observables to the same type, eg. Observable<Boolean>
, so you can merge them:
observable1.map(String s -> "...".equals(s))
observable2.map(Integer i -> i > 0 && i < 100)
observable3.map(MyClass m -> true)
...
2) Use Observable.merge()
to merge them all into single stream. Using zip
for this purpose will only work if all observables emit the same number of items, otherwise it will complete as soon as the first one completes, without waiting for the rest.
Observable<Boolean> allInOne = Observable.merge(observable1, observable2, ...);
3) myDelayedObservable
is just one of those observables that shall hold allInOne
incomplete until some listener calls back. Use Subject
for this purpose:
Subject<Boolean> myDelayedObservable = PublishSubject.create();
4) When your listener is ready, call myDelayedObservable.onComplete()
.
5) Subscribe to allInOne
and react on completion:
allInOne.subscribe(b -> { ... }, e -> { ... },
() -> { ... go ahead with your next task ... });
回答2:
Try with:
PublishSubject<Boolean> myDelayedObservable = PublishSubject.create<>();
or for RxJava2
PublishProcessor<Boolean> myDelayedObservable = PublishProcessor.create<>();
And when ready just call
myDelayedObservable.onNext(true)
//not this, myDelayedObservable.onComplete();
来源:https://stackoverflow.com/questions/41856356/rx-java-observable-execute-until-some-condition