ReactiveX / rxdart

The Reactive Extensions for Dart
http://reactivex.io
Apache License 2.0
3.37k stars 270 forks source link

BehaviorSubject Question #192

Closed bagintz closed 6 years ago

bagintz commented 6 years ago

I am not sure if I am thinking of this right, but I am using rxdart with BLoC's in flutter and I seem to be hitting a roadblock.

Everything works great when thinking in terms of everything being streams inside widgets, etc. Let's use the itemCount example from Filip Hracek (https://medium.com/flutter-io/build-reactive-mobile-apps-in-flutter-companion-article-13950959e381). Everything in there looks good. But....

What if, instead of getting the itemCount in a widget to display to the UI I wanted to have it available to put in an "share intent", so I can send a message that says "I have X number of items in my cart"

It seems overkill to have to create a BehaviorSubject.stream.listen(.....) and then to cancel that after you get the single number.

Is there no way, from a stream (since BLoC's suggest you only expose Streams and Sinks) to just get the last value from that stream cleanly?

If I am asking the wrong thing or in the wrong place, please let me know!

brianegan commented 6 years ago

Hey there! Yes, this is indeed an interesting problem. In fact, not only might you need to share that data synchronously with a ShareIntent, but you also might need to provide the data to the StreamBuilder's initialData property.

To help with this, we've recently introduced the ValueObservable class, which is implemented by BehaviorSubject. ValueObservables are normal Observables that also provide access to the latest value via observable.value.

This work has just been published as part of the 0.19.0 release. In order to use it, you can expose a ValueObservable to your Widgets instead of a normal Stream.

bagintz commented 6 years ago

Awesome! I will take a look. What I did in the meantime was just to create a getter that returned the .value from the BehaviorSubject that was the source of the stream in question. It seems this works the same*.

Does the work in 0.19.0 that you are referring to still honor the third rule of BLoC's?:

...rely on exclusive use of Streams for both input (Sink) and output (stream)...

Thanks!

[edit] - **or similar

bagintz commented 6 years ago

@brianegan this works if using the stream of the subject but doesn't seem to like, out of the box, the transformers like distinct, as those return an observable as opposed to valueobservable. Am I doing something wrong?

brianegan commented 6 years ago

Hrm, if you transform a ValueObservable at this time it will always return a raw Observable. I was kind of thinking of the ValueObservable as the final transformation you'd do, but that might be wrong. Just to help me understand your use-case, could you describe what you're doing?

For example, you can convert a normal observable into a ValueObservable like so: Observable.just(1).map().flatMap().shareValue().

Interesting case, thanks for pointing it out!

bagintz commented 6 years ago

@brianegan What I am doing currently, using 0.19.0 in my BLoCs, is:

....
//Output
final _loggedInUser = BehaviorSubject<UserProfile>();
Observable<UserProfile> get loggedInUserStream => _loggedInUser.stream.distinct();
ValueObservable<UserProfile> get loggedInUser => _loggedInUser.stream;

//Input
final _loginUserController = BehaviorSubject<UserProfile>();
Sink<UserProfile> get loginUser => _loginUserController.sink;
....

So I am using the Bloc.loggedInUser.value as the "last value" from the stream, but since the ValueObservable does not allow for distinct, I have to do it with 2 getters.

If the ValueObservable was transformable, I could just use loggedInUserStream.value in my code.

Again, I might be missing something. Ultimately this works fine, it is just one more variable to manage for each stateful object I want to track.

lukepighetti commented 5 years ago

Hi there, I transform multiple streams into output streams and I would like these to be ValueObservables. I have not found a way to turn an Observable into a ValueObservable as the final step. It there documentation surrounding this? There is no documentation for ValueObservable that I can find.

Edit: it looks like you can call .shareValue() on the end but im not sure if this makes the stream a broadcast and emit last value on listen like a BehaviorSubject.

feinstein commented 4 years ago

@brianegan is it there any differences between .shareValue() and a BehaviorSubject? I think this should be documented into .shareValue() as I believe its a common thing to think of when first learning about it.