I have three Observables which I combine with combineLastest:
Observable<String> o1 = Observable.just("1");
Observable<String> o2 = Observable.just("2");
Observable<String> o3 = Observable.just("3");
Observable.combineLatest(o1, o2, o3, new Func3<String, String, String, Object>() {
#Override
public Object call(String s, String s2, String s3) {
return null;
}
});
I want to be notified about the first emission of one of the Observables without ignoring the later emissions, which I guess first operator would do. Is there a convenient operator for that like (example):
o1.doOnFirst(new Func1<String, Void>() {
#Override
public Void call(String s) {
return null;
}
})
I think you can have a practical doOnFirst with a simple take if you're handling a stream:
public static <T> Observable<T> withDoOnFirst(Observable<T> source, Action1<T> action) {
return source.take(1).doOnNext(action).concatWith(source);
}
This way the action is only bound to the first item.
This could be changed to handle observables which are not backed by streams adding skip to skip the already taken items:
public static <T> Observable<T> withDoOnFirstNonStream(Observable<T> source, Action1<T> action) {
return source.take(1).doOnNext(action).concatWith(source.skip(1));
}
For convenience, I created these extension functions for Flowable and Observable.
Note, that with doOnFirst() the action will be called before the first element emission, whilst doAfterFirst() will firstly emit the first item and then perform the action.
fun <T> Observable<T>.doOnFirst(onFirstAction: (T) -> Unit): Observable<T> =
take(1)
.doOnNext { onFirstAction.invoke(it) }
.concatWith(skip(1))
fun <T> Flowable<T>.doOnFirst(onFirstAction: (T) -> Unit): Flowable<T> =
take(1)
.doOnNext { onFirstAction.invoke(it) }
.concatWith(skip(1))
fun <T> Observable<T>.doAfterFirst(afterFirstAction: (T) -> Unit): Observable<T> =
take(1)
.doAfterNext { afterFirstAction.invoke(it) }
.concatWith(skip(1))
fun <T> Flowable<T>.doAfterFirst(afterFirstAction: (T) -> Unit): Flowable<T> =
take(1)
.doAfterNext { afterFirstAction.invoke(it) }
.concatWith(skip(1))
Usage is as simple as this:
Flowable.fromArray(1, 2, 3)
.doOnFirst { System.err.println("First $it") }
.subscribe { println(it) }
Output:
// First 1
// 1
// 2
// 3
And:
Flowable.fromArray(1, 2, 3)
.doAfterFirst { System.err.println("First $it") }
.subscribe { println(it) }
Output:
// 1
// First 1
// 2
// 3
There are a couple of solutions I can think of.
The first one is an ugly but simple hack of doOnNext. Just add a boolean field to the Action1 indicating whether the first item has been received. Once received, do whatever it is you want to do, and flip the boolean. For example:
Observable.just("1").doOnNext(new Action1<String>() {
boolean first = true;
#Override
public void call(String t) {
if (first) {
// Do soemthing
first = false;
}
}
});
The second one is to subscribe twice on the observable you want to monitor using publish or share(), with one of those publications going through first (depending on whether you want to manually connect to the published observable). You'll end up with two separate observables that emit the same items, only the first one will stop after the first emission:
ConnectableObservable<String> o1 = Observable.just("1").publish();
o1.first().subscribe(System.out::println); //Subscirbed only to the first item
o1.subscribe(System.out::println); //Subscirbed to all items
o1.connect(); //Connect both subscribers
Using rxjava-extras:
observable
.compose(Transformers.doOnFirst(System.out::println))
It's unit tested and under the covers just uses a per-subscription counter in an operator. Note that per-subscription is important as there are plenty of uses cases where an observable instance gets used more than once and we want the doOnFirst operator to apply each time.
Source code is here.
Related
I need to chain two observables, the second depends on the first.
So what I have is:
Observable 1 -> petition returns Observable<TvShow>
//kotlin
fun getTvShow(): Observable<TvShow> {
return retrofitPetitionGetShow()...
}
//java
Observable<TvShow> getTvShow(){
return retrofitPetitionGetShow()...
}
Observable 2 -> returns Single<List<Season>>
Observable.range(1, TvShow.totalSeasons)
.flatMap { seasonNumber: Int ->
retrofitPetitionGetSeason(seasonNumber)....
}.toList()
What I need is the result of the second observable (List<Season>) to be added to the TvShow object TvShow.setList(List<Season>) and then return it.
Thank you in advance
Basing on provided information in comments you can try with the following code (it is Java code but it should be easy to convert that to Kotlin):
private Observable<TvShow> getTvShow() {
return retrofitPetitionGetShow();
}
private Single<List<Season>> getSeasons(TvShow tvShow) {
return Observable.range(1, tvShow.getTotalSeasons())
.flatMap(seasonNumber -> retrofitPetitionGetSeason(seasonNumber))
.toList();
}
public Observable<TvShow> chainObservables() {
return getTvShow()
.flatMap(tvShow -> getSeasons(tvShow).map(tvShow::withSeasons).toObservable());
}
IMPORTANT!
In reactive/functional way you should not modify objects, but create the new one (in your case, there is an update of tvShow with seasons list). There is a tvShow::withSeasons method reference which is implemented in this way:
public TvShow withSeasons(List<Season> seasons) {
return this.seasons == seasons ? this : new TvShow(this.name, this.totalSeasons, seasons);
}
This is an offshoot of my other question: How to chain Optional#ifPresent() in lambda without nesting?
However, the problem now is how to provide a lambda solution where all of the optional values are available at the innermost scope:
B b = procA().flatMap(this::procB).orElseThrow(SomeException::new);
// Value from procA() is not available.
My original code was:
void SomeMethod() {
procA().ifPresent(a -> {
procB(a).ifPresent(b -> {
// Do something with a and b
return;
});
});
throw new SomeException();
}
I understand that the return at the innermost scope is wrong. The new flatMap example illustrates the correct behavior.
I am using ifPresent() instead of get() to avoid potential runtime exceptions where I might fail to check whether the value of an optional isPresent().
I find this question very interesting as chained calls with potential null returns are a common nuisance, and Optional can shorten the usual null check chain a lot. But the issue there is that the nature of the functional stream methods hides the intermediate values in the mapping functions. Nesting is a way to keep them available, but can also get annoying if the length of the call chain grows, as you have realized.
I cannot think of an easy and lightweight solution, but if the nature of your project leads to these situations regularly, this util class could help:
public static class ChainedOptional<T>
{
private final List<Object> intermediates;
private final Optional<T> delegate;
private ChainedOptional(List<Object> previousValues, Optional<T> delegate)
{
this.intermediates = new ArrayList<>(previousValues);
intermediates.add(delegate.orElse(null));
this.delegate = delegate;
}
public static <T> ChainedOptional<T> of(T value)
{
return of(Optional.ofNullable(value));
}
public static <T> ChainedOptional<T> of(Optional<T> delegate)
{
return new ChainedOptional<>(new ArrayList<>(), delegate);
}
public <R> ChainedOptional<R> map(Function<T, R> mapper)
{
return new ChainedOptional<>(intermediates, delegate.map(mapper));
}
public ChainedOptional<T> ifPresent(Consumer<T> consumer)
{
delegate.ifPresent(consumer);
return this;
}
public ChainedOptional<T> ifPresent(BiConsumer<List<Object>, T> consumer)
{
delegate.ifPresent(value -> consumer.accept(intermediates, value));
return this;
}
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
throws X
{
return delegate.orElseThrow(exceptionSupplier);
}
public <X extends Throwable> T orElseThrow(Function<List<Object>, X> exceptionSupplier)
throws X
{
return orElseThrow(() -> exceptionSupplier.apply(intermediates));
}
}
You use it by wrapping an Optional or a plain value. When you then use the map method to chain method calls, it will provide a new ChainedOptional while storing the current value in a list. At the end (ifPresent, orElseThrow), you will not only get the last value, but also the list of all intermediate values. Since it is not known how many calls will be chained, I did not find a way to store those values in a type-safe way, though.
See examples here:
ChainedOptional.of(1)
.map(s -> s + 1)
.map(s -> "hello world")
.map(s -> (String) null)
.map(String::length)
.ifPresent((intermediates, result) -> {
System.out.println(intermediates);
System.out.println("Result: " + result);
})
.orElseThrow(intermediates -> {
System.err.println(intermediates);
return new NoSuchElementException();
});
// [1, 2, hello world, null, null]
// Exception in thread "main" java.util.NoSuchElementException
// at ...
ChainedOptional.of(1)
.map(s -> s + 1)
.map(s -> "hello world")
// .map(s -> (String) null)
.map(String::length)
.ifPresent((intermediates, result) -> {
System.out.println(intermediates);
System.out.println("Result: " + result);
})
.orElseThrow(intermediates -> {
System.err.println(intermediates);
return new NoSuchElementException();
});
// [1, 2, hello world, 11]
// Result: 11
Hope this helps. Let me know if you come up with a nicer solution.
I'm very new to RxJava. I have a problem with converting a nested async operation into RxJava structure. Having a single async task that fetches data from the server has not been a problem to create, however I do have a problem with an exemplary case of this sort:
List<A> aaa = new ArrayList<>();
List<B> bbb = new ArrayList<>();
new FetchItemA(String id){
#Override
protected void onPostExecute(List<A> items){
foreach(A item:items){
new FetchItemB(item.getId())
#Override
protected void onPostExecute(List<B> newItems){
neededList.addAll(newItems);
}
}
}
}
}
The problem is with the return types. I've created my observable this way:
Observable.fromArray(String userId)
.map(new Function(String, List<A>){
#Override
public List<A> apply(String id){
return getListA();
}
})
.map(new Function<String, List<B>){
#Override
public List<B> apply(String id){
someList.add(getItemB(id));
return someList;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer(){
#Override
public void onCompleted(List<B> items){
bbb.addAll(items);
adapter.setItems(bbb);
}
});
This however is illegal as this Observableexpects the type List<A>whereas I'm returning List<B>. How can I structure my RxJava observable to be able to fetch a list of items (of type A, each having a unique id), and based on the fetched list, fetch a single item (of type B) with id (of each item of type A in the first list) as the argument, and only after add the received items (of type B) to a list?
The essential step in fetching the data is to transform each A into a B using a network call. In the RxJava world, that means wrapping the network call in an observable and then using the flatMap() operator.
Observable.fromList(aaa)
.flatMap(new Func1<A, Observable<B>>() {
#Override
public Observable<B> call(A a) {
return Observable.fromCallable(getNetworkValueAsB(item));
}
} )
.toList()
.subscribe( new Observer<List<B>>() {
#Override
public void onNext(B bItemList) {
bbb.addAll(bItemList);
adapter.setItems(bbb);
}
});
The operations are fromList() which converts from the List<A> to Observable<A>, flatMap() which converts from A to B using the call, and toList() which gathers all the B values produced into a list, which is then used in the subscription.
The fromList() operator might be called fromIterable() or from() depending on the version of the library you are using.
Edited to removed lambdas
Can we detect if a class member value is getting changed using RxJava?? Say in a class there is a variable var, now can we get notified whenever the value of var changes using RxJava.
You can use something like this:
private final BehaviorSubject<Integer> subject = BehaviorSubject.create();
private Integer value=0;
public Observable<Integer> getUiElementAsObservable() {
return subject;
}
public void updateUiElementValue(final Integer valueAdded) {
synchronized (value) {
if (valueAdded == 0)
return;
value += valueAdded;
subject.onNext(value);
}
}
and subscribe to it like this:
compositeSubscription.add(yourClass.getUiElementAsObservable()
.subscribe(new Action1<Integer>() {
#Override
public void call(Integer userMessage) {
setViews(userMessage,true);
}
}));
you have to create setter for all of your variables that you want something subscribe to their changes and call onNext if change applied.
UPDATE
When an observer subscribes to a BehaviorSubject, it begins by emitting the item most recently emitted by the source Observable
you can see other type of subjects here: http://reactivex.io/documentation/subject.html
some useful link:
about reactive programming : https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
and about rxjava : https://youtu.be/k3D0cWyNno4
http://rxmarbles.com/#distinctUntilChanged
Code
Observable.just("A", "B", "B", "A", "C", "A", "A", "D")
.distinctUntilChanged()
.subscribe(abc -> Log.d("RXJAVA", abc));
Result
A
B
A
C
A
D
I'm using RxJava, and I need to do 2 things:
Get the last element emitted from the Observable
Determine if onError was called, vs. onCompleted
I've looked at using last and lastOrDefault (which is actually the behavior I need), but I've not been able to work around onError hiding the last element. I would be OK with the Observable being used twice, once to get the last value and once to get the completion status, but so far I've only been able to accomplish this by creating my own Observer:
public class CacheLastObserver<T> implements Observer<T> {
private final AtomicReference<T> lastMessageReceived = new AtomicReference<>();
private final AtomicReference<Throwable> error = new AtomicReference<>();
#Override
public void onCompleted() {
// Do nothing
}
#Override
public void onError(Throwable e) {
error.set(e);
}
#Override
public void onNext(T message) {
lastMessageReceived.set(message);
}
public Optional<T> getLastMessageReceived() {
return Optional.ofNullable(lastMessageReceived.get());
}
public Optional<Throwable> getError() {
return Optional.ofNullable(error.get());
}
}
I've no problem with making my own Observer, but it feels like Rx should be better able to meet this use-case of "get the last element emitted before completion`". Any ideas on how to accomplish this?
Try this:
source.materialize().buffer(2).last()
In the error case the last emission will be a list of two items being the last value emitted wrapped as a Notification and the error notification. Without the error the second item will be the completion notification.
Note also that if no value is emitted then the result will be a list of one item being the terminal notification.
I solved with:
source.materialize().withPrevious().last()
where withPrevious is (Kotlin):
fun <T> Observable<T>.withPrevious(): Observable<Pair<T?, T>> =
this.scan(Pair<T?, T?>(null, null)) { previous, current -> Pair(previous.second, current) }
.skip(1)
.map { it as Pair<T?, T> }
Have you try onErrorResumeNext here you can see the rest or error handling operators https://github.com/ReactiveX/RxJava/wiki/Error-Handling-Operators
I used this approach to solve your problem.
public class ExampleUnitTest {
#Test
public void testSample() throws Exception {
Observable.just(1, 2, 3, 4, 5)
.map(number -> {
if (number == 4)
throw new NullPointerException();
else
return number;
})
.onErrorResumeNext(t -> Observable.empty())
.lastOrDefault(15)
.subscribe(lastEmittedNumber -> System.out.println("onNext: " + lastEmittedNumber));
}
}
It will emit onNext: 3
Hope that it helps.