Evaluate startwith's param when subscribing - reactive-programming

observableEmitingItemsRegularly
.map(this::cacheLastItem) //set the object in lastItem variable
.startWith(lastItem);
Returns always the same object at the beginning: The value interpreted at the time that line got interpreted.
I already tried:
Changing
.startWith(lastItem);
with
.startWith(getLastItem());
The function getLastItem() is called when we initialize the observable, not when we subscribe as I want to.
Many Thanks !

Have you tried using Defer
From the documentation:
Defer do not create the Observable until the observer subscribes, and
create a fresh Observable for each observer
.startWith(Observable.defer(() -> Observable.from(getLastItem()));

Related

PassthroughSubject with no initial value

I want to create a Swift Combine publisher that transmits a value and always gives the latest value when someone subscribes to it. However I want to only transmit a value once I have one - from an asynchronous call that’s triggered by the first subscriber. Pass through subject doesn’t work for that need, is there any good way to accomplish this?
You can use CurrentValueSubject for this:
let subject = CurrentValueSubject<T, E>(someValue)
func whatever() -> AnyPublisher<T, E> {
return subject.dropFirst().eraseToAnyPublisher()
}

StreamBuilder triggers a method twice while the same operation as a variable triggered only once

I have a StreamBuilder that accepts a stream from my service. It looks like this:
StreamBuilder(
stream: MyService.getStream$()
builder (...)
);
Plus, I have my service with the following method:
getStream$() {
print('being printed twice');
return Observable.just('text')
.doOnData(() => print('being printed twice too'));
}
When I run the app, I get the following prints being printed twice (each).
But, when I change the following implementation as a variable, it runs just once:
Observable getStream = Observable
.just('text')
.doOnData((data) => print('being printed once');
Of course, in the example above, I would use variables, but in my original code, I'm unable to do so because I'm depended on the instance properties.
What I can do, is to declare an Observable variable and in the constructor to set it to my desired observable. Although, this solution sounds like a workaround, and I'm not sure why would the the method would be triggered twice.
Any ideas?
StreamBuilder is rebuild every time build method is invoked. It means that MyService.getStream$() is evaluated with each invocation and creates new Observable. If you assign Observable to variable it will be created once and reused between build calls.
Take a look at this question Future running twice because it's in build method, how to fix it?
it's about future but the mechanism is same.

Correct way to restart observable interval in RxSwift

In my OS X status bar app I'm using interval function to periodically call an external api and display the result:
Observable<Int>
.interval(120.0, scheduler: MainScheduler.instance)
.startWith(-1) // to start immediately
.flatMapLatest(makeRequest) // makeRequest is (dummy: Int) -> Observable<SummaryResponse?>
.subscribeNext(setSummary)
.addDisposableTo(disposeBag)
However, if user changes the preferences in the meantime, I would like to "restart" this interval and make a new call immediately to reflect the changes (without having to wait for the next call).
What's the best way to do this?
Store the observable as a property and set it to nil or call .dispose() on it (or both) and create a new observable ?
Set disposeBag to nil and create a new observable ?
Any other way?
What you're looking for is merge. You have two Observables, one of which is an interval and the other which represents preference changes. You want to merge those into one Observable with the elements from both, immediately as they come.
That would look like this:
// this should really come from somewhere else in your app
let preferencesChanged = PublishSubject<Void>()
// the `map` is so that the element type goes from `Int` to `Void`
// since the `merge` requires that the element types match
let timer = Observable<Int>.timer(0, period: 3, scheduler: MainScheduler.instance).map { _ in () }
Observable.of(timer, preferencesChanged)
.merge()
.flatMapLatest(makeRequest)
.subscribeNext(setSummary)
.addDisposableTo(disposeBag)
Also notice how I'm using timer instead of interval, since it allows us to specify when to fire for the first time, as well as the period for subsequent firings. That way, you don't need a startWith. However, both ways work. It's a matter of preference.
One more thing to note. This is outside of the scope of your question (and maybe you kept it simple for the sake of the question) but instead of subscribeNext(setSummary), you should consider keeping the result as an Observable and instead bindTo or drive the UI or DB (or whatever "summary" is).

How to pass a variable along when chaining observables?

I'm pretty new to RxJava, and whenever I have a case where I need to pass return data from one observable down the chain until a call to 'subscribe' - I have trouble understanding how to do it the 'Reactive' way without any patches...
For example:
Observable<GameObject> obs1 = func1();
Observable<GameObject> obs2 = func2();
Observable<GameObject> obs3 = func3();
Observable<GameObject> obs3 = func4();
I would like to emit obs1 and obs2, get their result, then emit obs3 then obs4 and then end the chain with subscribe while having the access to the results of obs1,obs2,obs3 and obs4.
The order of the calls is important, I need obs1 and obs2 to complete before obs3 is executed.
same goes for obs3 and obs4 - I need obs3 to complete before obs4 is executed.
How can I do that?
I know it's a pretty digested question - but this is one of the most problematic issues when a developer starts to know rxJava.
Thanks.
You can do it using Observable.zip and simple Observable.map/Observable.flatMap:
Observable.zip(obs1, obs2, (res1, res2) -> {
// do stuff with res1, res2
return obs3.flatMap(res3 -> {
// do stuff with res1, res2, res3
return obs4.flatMap(res4 -> {
// do stuff with res1, res2, res3, res4
return result;
});
});
});
This will force your scheduling requirements:
observables 1 and 2
observable 3
observable 4
Since I had the same kind of doubts in mind a while ago, the question seams to be related to how Observables really work.
Let's say you created obs1 and obs2 using something like:
Observable<GameObject> obs1 = Observable.create(...)
Observable<GameObject> obs2 = Observable.create(...)
You have 2 independent and disconnected streams. That's what you want when each of them are supposed to do something like a network request or some intensive background processing, which can take some time.
Now, let's say you want to watch for both results and emit a single value out of them when they get ready (you didn't say explicitly that, but it's gonna help you understand how it works). In this case, you can use the zipWith operator, which takes a pair of items, the first item from the first Observable and the second item from the second Observable, combine them into a single item, and emit it to the next one in the chain that may be interested on it. zipWith is called from an Observable, and expects another Observable as param to be zipped with. It also expects a custom function that knows how to zip the 2 source items and create a new one out of them.
Observable<CustomObject> obs3 = obs1.zipWith(obs2, new Func2<GameObject, GameObject, CustomObject>() {
#Override
public CustomObject call(GameObject firstItem, GameObject secondItem) {
return new CustomObject(firstItem, secondItem);
}
});
In this case, the CustomObject is just a pojo. But it could be another long running task, or whatever you need to do with the results from the first two Observable items.
If you want to wait for (or, to observe!) the results coming from obs3 you can plug another Observable at the end, which is supposed to perform another piece of processing.
Observable<FinalResult> obs4 = obs3.map(new Func1<CustomObject, FinalResult>() {
#Override
public FinalResult call(CustomObject customObject) {
return new FinalResult(customObject);
}
});
The map operator transforms (or maps) one object into another. So you could perform another piece of processing, or any data manipulation, and return a result out of it. Or your FinalResult might be a regular class, like CustomObject, just holding references to the other GameObjects.. you name it.
Depending how you created your Observables, they may not have started to emit any items yet. Until now you were just creating and plugging the data pipes. In order to trigger the first task and make items flow in the stream you need to subscribe to it.
obs4.subscribe();
Wrapping up, you don't really have one single variable passing along the whole chain. You actually create an item in the first Observable, which notifies the second one when it gets ready, and so on. Additionally, each step (observable) transforms the data somehow. So, you have a chain of transformations.
RxJava follows a functional approach, applying high order functions (map, zip, filter, reduce) to your data. It's crucial to have this clear. Also, the data is always immutable: you don't really change an Observable, or change your own objects. It creates new instances of them, and the old objects will eventually be garbage collected. So obs1.zip(...) doesn't change obs1, it creates a new Observable instance, and you can assign it to a variable.
You can also drop the variable assignments (obs1, obs2, obs3 etc) and just chain all methods together. Everything is strongly typed, so the compiler will not let you plug Observables that don't match each other (output of one should match input of the next).
I hope it gives you some thoughts!

What is this ScalaRX code doing?

So I'm pretty new to both Scala and RX. The guy who knew the most, and who actually wrote this code, just left, and I'm not sure what's going on. This construct is all over his code and I'm not really clear what its doing:
def foo(List[Long]) : Observable[Unit] =
Observable {
subscriber => {
do some stuff
subscriber.onNext()
subscriber.onCompleted()
}
I mostly get do some stuff, and the calls to subscriber. What I don't get is, where does subscriber come from? Does subscriber => { instantiate the subscriber? What does Observable { subscriber => { ... } } do/mean?
If you take a look at the Observable companion object documentation, you will see an apply method that takes a function of type (Subscriber[T]) ⇒ Unit. So, when you call Observable{withSomeLambda}, then this is the same as calling Observable.apply{withSomeLambda}
And, if you go all the way to the source code you will see that this is really returning
toScalaObservable(rx.Observable.create(f))
where f is the lambda that you passed in.
So, subscriber is just the parameter of the lambda. It is passed in by the caller of that function.
This code is creating a new Observable as described here.
Basically when a downstream component subscribes to this stream, this callback is called. In the callback we determine when we, as a data source, will call onNext(v: T) which is how we pass each element we are generating to them, and when we will call onCompleted() which is how we tell the subscriber that we are done sending data.
Once you have created an Observable you can start calling Observable operators, which will either result in another, compound Observable, or will result in a terminating condition which will end the process, and generally result in a final result for the flow (often a collection or aggregate value).
You don't use the List in your question, but normally if you wanted to make a reactive stream out of a list you would call Observable.from().
PS: I think this is RxJava code.