Reputation: 397
I'm using RxAndroid 2.0.1 with RxJava 2.0.6.
I have two observables: one returns Maybe<MyObject>
based on some String (ID). When the optional object is returned, I have to call the second one that takes the MyObject instance and returns Single<Boolean>
if object meets some conditions. Then I can do some further operations with the object instance.
My current implementation is as follows:
objectDAO.getById(objectId)
.subscribe(
myObject -> checkCondition(myObject),
throwable -> /* Fallback */,
() -> /* Fallback */
);
private void checkCondition(final MyObject myObject) {
otherDAO.checkCondition(myObject)
.subscribe(
isTrue -> {
if (isTrue) {
// yay! now I can do what I need with myObject instance
} else {
/* Fallback */
}
},
throwable -> /* Fallback */
);
}
Now I'm wondering how could I simplify my code. My ideas:
Try to use zip
- I can't because second Observable can't be subscribed until the first one returns the MyObject
Try to use filter
- Now the issue is that I need to use blocking get to call second observable. It will propably work, but looks like a code smell:
objectDAO.getById(objectId)
.filter(myObject ->
otherDAO.checkCondition(myObject).blockingGet()
)
.subscribe(
myObject -> checkCondition(myObject),
throwable -> /* Fallback */,
() -> /* Fallback */
);
Try to use flatMap
- The second observable returns Boolean while I need to return the original object. Because of that I need to mape a code snippet with blockingGet
and return original object or Maybe.empty()
Any suggestions how to do it in such a way that the code is "clean" (it's smaller and it's still clear what's happening inside)?
Upvotes: 5
Views: 2635
Reputation: 28301
The RxJava2Extensions extra project by akarnokd has a filterAsync
transformer (to be used with compose
) that does just that, using a any Publisher<Boolean>
;)
Upvotes: 1
Reputation: 2480
I've come up with solution without passing Pairs with boolean values, in case anybody will face same problem.
For example, if objectDAO.getById(objectId)
returns Observable<T>
and otherDAO.checkCondition(myObject)
returns Single<Boolean>
, we can handle filtering in such a way:
objectDAO.getById(objectId)
.flatMap(myObject -> otherDAO
.checkCondition(myObject)
.toObservable()
.filter(Boolean::booleanValue)
.map(o -> myObject))
.flatMapSingle(obj -> ...)
Unwanted objects will be resolved to Observable.empty
and thus filtered, so that only needed objects will get to .flatMapSingle(obj -> ...)
Basically, same thing can be achieved with slightly easier to understand structure (though, I've found the first one a bit nicer aesthetically):
objectDAO.getById(objectId)
.flatMap(myObject -> otherDAO
.checkCondition(myObject)
.flatMapObservable(isChecked -> isChecked ? Observable.just(myObject) : Observable.empty()))
.flatMapSingle(obj -> ...)
Upvotes: 0
Reputation: 12982
One thing you could do:
objectDAO.getById(objectId)
.flatMapSingle(myObject -> otherDAO
.checkCondition(myObject)
.map(isTrue -> Pair.create(myObject, isTrue))
)
Then you have an Observable<Pair<MyObject, Boolean>>
and can proceed however you want: subscribe
directly and check the Boolean
there, filter
by the Boolean value, etc.
Upvotes: 5