I've seen patterns like this:
Observable<String> nameChanges = nameDataSource.changes().share();
// One subscriber
autoUnsubscribe(nameChanges.subscribe(() -> { ... }));
// Another subscriber
autoUnsubscribe(nameChanges.map(...).filter(...).subscribe(...));
// autoUnsubscribe is called when the UI is torn down
My question is:
Why is it necessary to call share() whenever I want to listen to the Observable in multiple places?
Why is not share() the default behavior for all observables?
It would be nice if the code above worked the same even without .share(). I would not have to think about when I need to share an Observable, and when I don't.
Is it for performance reasons because having a single subscriber is a special case that can be handled more efficiently?
From the docs this is not clear to me:
share() returns a new ObservableSource that multicasts (shares) the original ObservableSource. As long there is at least one Observer this ObservableSource will be subscribed and emitting data.
There are two kinds of Observables: cold and hot. Cold Observables start producing items when there is an Observer to them and they do it on an individual basis. Subscribing with multiple Observers will result in multiple runs of the same cold Observable. An example of this is an Observable that issues a network request.
In contrast, a hot Observable can produce items with or without the presence of Observers. These Observables usually multicast the same items to all of their current Observers. An example of this is an Observable of button clicks.
To turn a cold Observable into a hot one, you can use publish() which will make sure only a single subscription is established to the source Observable no matter how many Observers there are. Thus, the chain will now act as a hot multicasting Observable from the Observers' perspective.
However, often it is not economic to keep an originally cold Observable running after all Observers of publish() have gone away, therefore the refCount() operator can be used to keep track of them and stop the source when there are no interesting parties left.
If your source is already hot, you don't need share().
Why is not share() the default behavior for all observables?
Actually, this property is one of the important contributions of the modern reactive programming paradigm: the distinction of the hot and cold Observables.
However, multicasting is expensive on itself because you have to keep track of the set of current Observers in order to notify them with new events, and this can lead to all sorts of logical race conditions to be defended against. A cold Observable is known to talk only to a single Observer so there is no need for the extra tracking overhead.
I would not have to think about when I need to share an Observable, and when I don't. I'm afraid that you will have to think when programming. ;)
In the above code, yes, sharing makes sense. But what if you we're updating something on the backend, using the same network and method call from two different points, updating with different data? You would have the same call with the same Observable, but you certainly wouldn't want to share the Observable instance (and the network call) because that means that all successive calls with data would be discarded in the favour of the first one. Or if you wanted to start a timer whenever you're subscribed, you again wouldn't want to share this with other Observables.
Also, it is much easier to add certain behaviour than to remove it. For example, if sharing was the default, and the second subscriber wouldn't want to share and removes the sharing - what about the third one? Will it share it with the first one or not? At that point the sharing property becomes the property of the Subscriber and not the Observable and you would have no clear way of knowing which one is shared and which one isn't.
Related
In the past, I was using LocalBroadcastManager and EventBus in my chat and taxicab applications which are now either deprecated or not recommended using them.
I intend to replace them with new data structures like mutablesharedflow or channel,
i want to know which one is better matched with my case? or maybe another data structure?
From Roman Elizarov, Channels were added as an inter-coroutine communication primitive.
You cannot use channels to distribute events or state updates in a way that allows multiple subscribers to independently receive and react upon them.
So they introduced Flow. But Flow is a cold observable, where every subscriber gets their own data (independent from other subscribers). With SharedFlow you get a hot observable that emits independently of having any subscriber(s).
You could do the same with ConflatedBroadcastChannel. But JetBrains recommend to use Flow in favor of Channels because of their simpler API.
So if you want to migrate to Coroutines and you need a hot observable multiple subscribers can listen to, you should go with SharedFlow.
Both are good for listening one time events. Everything depends in your use cases.
SharedFlow known as hot flow ->
Emit events even if no observer is listening to it
If no observer is listening to it, you loose these events
Channels known as cold flow
Does not emit events when no observer is not listening to it. It works like a BlockingQueue.
When you start to collect, it collects all data which were sent.
I'm new to RxJava and currently, I'm understanding things through examples. One thing is always confusing me, and so far I couldn't find any better document to understand it clearly. Flowable Vs Observable, when to use which
As per my understanding, Flowable supports backpressure whereas Observable doesn't. Which means If you don't want to lose any stream (Such as UI events like mouse move, keyboard text entry) You should go for Observable.
If your emitter is emitting continues items, and you have a slower consumer, go for Flowable, It will manage out of memory errors by caching only limited amount of items
Alright, But in many samples and docs, I saw people using and recommend Flowable for network requests and disk operations. Including the googlesamples. But why? Why is Flowable best over Observable here? You will be hitting the API for a single response, and you would expect a limited set of result only, It is not like a continues emitter as the mouse move listener. So what makes it better to use Flowable here over observable?
Also, for a beginner like me, it would be helpful if someone could explain some of the common use cases to go for Flowable or Observable in simple words.
At least in mobile apps BehaviorSubject is used frequently, to model a property - it has a current value, which can be queried any time, and be observed.
Sometimes it's wanted to just transform a BehaviorSubject without subscribing to it. E.g. if there's class, that acts as an intermediate layer between several transformed BehaviorSubject and potential subscribers.
The issue I have encountered here, at least with RxJava2, is that applying operators on BehaviorSubject returns always Observable. So my intermediate layer can't offer anymore an api of BehaviorSubject.
A possible solution is to create new BehaviorSubjects and subscribe them to the original BehaviorSubject but this seems a bad idea overall, maybe I don't want to subscribe at this moment but only on demand, i.e. when the users of my intermediate layer actually needs these subjects?
In my case the context is an Android app with MVVM pattern, where the view model exposes BehaviorSubject to the views, which are for the most part derived from another BehaviorSubjects in the app. I currently went with subscribing in the view model, but I would like to improve this since the view model isn't really the consumer and shouldn't be subscribing to anything - the subjects should be activated when the view actually needs something from them.
And no I can't use only Observable in the view model as there are unit tests and some other calls that check for the value at a point, which can't be done using only Observable.
My main question is why is it not possible to simply be able to transform BehaviorSubject into another BehaviorSubject. A nice to have also, what is the recommended way to work with BehaviorSubject in the described context.
It would not compose properly, operators are final methods to avoid method dispatch problems. Plus, you'd create multiple entry points for and end consumer and possibly violate the Observable contract if you's onNext the transformed subject while also onNext the original subject.
But you can have multiple subjects merged together, each driven by its own respective events and the end consumers would receive events properly.
And no I can't use only Observable in the view model as there are unit tests and some other calls that check for the value at a point, which can't be done using only Observable.
Have you tried blockingFirst() to get the current value from a chain that starts from those original BehaviorSubject?
Otherwise, your design is unclear to me as it is too much focused on subjects other than being a single originator of some events.
I work with RxJava and RxAndroid. How resume the work of an observable if a configuration change occurs (activity rotation, language locale change etc.)?
I need not only resume the work of an observable, also I need save emitted items, when subscriber is unsubscribed and emit all saved items right away after subscription.
I read a ton of articles, but I didn't find the answer to my question.
I found a few examples, but none of them does not solve the problem:
https://github.com/alapshin/rxweather
https://github.com/kaushikgopal/RxJava-Android-Samples
https://github.com/tehmou/rx-android-architecture
https://github.com/richardradics/RxAndroidBootstrap
You can use one of the ConnectableObservables. Particularly, cache or replay would be handy for this kind of situation.
For example, you can call cache on your observable, unsubscribe it when activity is destroyed, and resubscribe it again after the activity is recreated.
I have made a demo application (https://github.com/pmellaaho/RxApp) in order to experiment how to tackle these kinds of situations. Basically, I use a singleton model from Activity to get the response from network. This makes it possible to cache responses, access the data from multiple UI components, subscribe to pending request and also to provide mock data for automated UI tests.
You can use OperatorFreeze from this library for pausing Observable when activity is recreating. You need pass instance of this operator to method Observable.lift(). You don't need to unsubscribe from Observables when you use persistent Presenter.
I have been using Event Bus in my apps (i.e: greenrobot/EventBus). But I find some disadvantages in using Event Bus:
Chaining tasks execution is difficult
A lot of classes to represent events
Less clear code (well, it's still possible to trace, but not as clear)
I have been researching for new techniques to deal with this problem. And I read quite a bit about RxJava and wonder if it could be a solution.
So my questions about RxJava (based on what I have read recently):
Could RxJava observer be registered at any time? So not just when creating the Observable. With EventBus this is possible, I could subscribe at any time, not just when the Observable is created.
How do you handle two or more publishers publishing the same type of event (e.g: navigation event)?
Tightly coupling the publisher(s) and the subscriber, means that I have to explicitly specify the publisher(s) every time. So I have to worry not just with the type of events, but also the originators. With EventBus, I only need to worry about the type of events and not the originators.
1) Once you have an instance of an Observable, you can subscribe to it at any time and from any thread, even concurrently.
2) We usually merge the streams of multiple observables via Observable.merge() or use a serialized PublishSubject.
3) If you observe an Observable, there could be dozens of upstream operators and sources involved, but you'll get a sequential stream of values no matter what. You only need to get a hold onto an Observable representing some source of events and the observer doesn't need to know if the event was merged, filtered, made a roundtrip over the network and got delayed before arriving in your onNext() method. You can naturally implement or use some lookup service that will get you an Observable to reduce the coupling, but with RxJava, coupling is not usually an issue.