I'm very new to RxJava, and I want to get content from 3 different webpages synchronously. How do I go about doing this?
You can use concat to make the calls happen in sequence:
Observable call1 = ...
Observable call2 = ...
Observable call3 = ...
Observable.concat(call1, call2, call3).subscribe(...);
You can use toBlocking to make the reception synchronous:
Observable.concat(call1, call2, call3).toBlocking().forEach(...);
I believe you want to achieve parallel execution of your observables, you can do this by using combineLastest operator. In short, you should create 3 observables and merge their results via combineLastest. In this case subscribe will be triggered once each observable emits something.
For further information, please see:
http://reactivex.io/documentation/operators/combinelatest.htm
Related
In rxJava 1 there was Scheduler.immediate() which let you schedule work on the current thread. In rxJava 3 I can no longer find this scheduler.
Does anyone know what the replacement for Scheduler.immediate() is in rxJava 3?
My use case:
I have a client-side API which I use to subscribe to an infinite stream of events (e.g. a news feed) from a remote server. The API notifies me of events via a callback which I register:
Observable.create(emitter -> apiClient.registerCallback(event -> emitter.onNext(event)))
.observeOn(Schedulers.immediate()) // I'd like downstream operators to run on current thread
.map(myFunc);
However, the API calls my callback from a different thread. I wish to run downstream computations like myFunc on the current thread (the one that created the Observable) so as not to block the API's thread.
AFAIK, in RxJava 3 you can employ ImmediateThinScheduler to obtain the same effect.
Although it's kept in the internal package, you can use it.
The API is so simple you can actually create one yourself if you don't want to depend on their internal package.
I have created a really simple example using RxJava 2 (everything I have developed was using RxJava 1) and I have found next behavior that I don't understand at all. I have next Observable with zip operation:
Observable.zip(getGame(gameId), getDetail(gameId), getReviews(gameId),
(game, detail, reviews) -> new GameInfo(game, detail, reviews))
.subscribeOn(Schedulers.newThread())
.subscribe(sendGameInfo(asyncResponse));
Each of the methods returns an instance of Observable. In theory, I would expect that each of the method (getGame, getDetail, ...) would be executed in parallel in a new Thread, but doing a sysout I noticed that all the time is the same Thread so they are not executed in parallel. I suppose that this is the expected behavior but if I would like to make in parallel is there a way to do it without having to define a runnable inside each of the observable?
Thank you very much.
Ok you need to subscribeOn every Observable
Observable.zip(getGame(gameId)
.subscribeOn(Schedulers.from(executor)),
getDetail(gameId)
.subscribeOn(Schedulers.from(executor)),
getReviews(gameId)
.subscribeOn(Schedulers.from(executor)),
(game, detail, reviews) -> new GameInfo(game, detail, reviews))
.subscribeOn(Schedulers.from(executor))
.subscribe(sendGameInfo(asyncResponse));
I'm trying to create a Flowable which is wrapping an Iterable. I push elements to my Iterable periodically but it seems that the completion event is implicit. I don't know how to signal that processing is complete. For example in my code:
// note that this code is written in Kotlin
val iterable = LinkedBlockingQueue<Int>()
iterable.addAll(listOf(1, 2, 3))
val flowable = Flowable.fromIterable(iterable)
.subscribeOn(Schedulers.computation())
.observeOn(Schedulers.computation())
flowable.subscribe(::println, {it.printStackTrace()}, {println("completed")})
iterable.add(4)
Thread.sleep(1000)
iterable.add(5)
Thread.sleep(1000)
This prints:
1
2
3
4
completed
I checked the source of the Flowable interface but it seems that I can't signal that a Flowable is complete explicitly. How can I do so? In my program I publish events which have some delay between them and I would like to be explicit when to complete the event flow.
Clarification:
I have a long running process which emits events. I gather them in a queue and I expose a method which returns a Flowable which wraps around my queue. The problem is that there might be already elements in the queue when I create the Flowable. I will process the events only once and I know when the flow of events stops so I know when I need to complete the Flowable.
Using .fromIterable is the wrong way to create a Flowable for your use case.
Im not actually clear on what that use case is, but you probably want to use Flowable.create() or a PublishSubject
val flowable = Flowable.create<Int>( {
it.onNext(1)
it.onNext(2)
it.onComplete()
}, BackpressureStrategy.MISSING)
val publishSubject = PublishSubject.create<Int>()
val flowableFromSubject = publishSubject.toFlowable(BackpressureStrategy.MISSING)
//This data will be dropepd unless something is subscribed to the flowable.
publishSubject.onNext(1)
publishSubject.onNext(2)
publishSubject.onComplete()
Of course how you deal with back-pressure will depend on the nature of the source of data.
Like suggested by akarnokd, ReplayProcessor do exactly what you want. Replace iterable.add(item) with processor.onNext(item), and call processor.onComplete() when you are done.
I'm working on an android project that makes requests through retrofit using Rx-Java observable and subscribe.
However, in some interactions this request can be called multiple times and I would like to only execute the last one in a predefined window of time (debounce).
I tried to apply the debounce operator directly to the observable, but it will not work because the code below is executed every time some interaction occurs:
mApi.getOnlineUsers()
.debounce(1, TimeUnit.SECONDS)
.subscribe(...)
I guess it should be created only one observable and every interaction it should "append" the execution to the same observable. But I am kind of new on Rx Java and don't know exactly what to do.
Thanks!
Suppose you want to start an execution according to some trigger event.
Observable<Event> trigger = ... // e.g. button clicks
You can transform the trigger events to calls to your API like this:
trigger
.debounce(1, TimeUnit.SECONDS)
.flatMap(event -> mApi.getOnlineUsers())
.subscribe(users -> showThemSomewhere(users));
Also, notice that the debounce operator will take the last occurrence within the time frame, but throttlefirst will take the first. You may want to use one or the other depending on your use case.
Imagine I have some time consuming task which I want to run only occasionally.
I want to wrap it into an observable and pass it to some component.
That component will subscribe to this observable whenever it wants to retrieve the data, and unsubscribe after it receives it.
I.e. I want an observable which upon subscription would invoke some expensive API call, and this API call can return a different data each time it is called - and then this observable would shut down until next subscription is made.
Is this possible to achieve?
I have seen 'replay()' and 'cache()' operators, but they won't work because from what I understood, they will cache once and then replay cached values which fails my case of changing data.
Also there is 'observable.publish()' but it seems that this will make a hot observable which will stay connected to the source observable all the time...
As I understand your question, you need a cold observable.
Observable<Integer> obs = Observable.from(1, 2, 3, 4);
obs.subscribe(); // will iter over values
obs.subscribe(); // will iter AGAIN over values
So, if your observable is your api call, and it's a cold observable, just subscribe twice on it to perform two api calls.