I am using concat operator to print all the items sequentially. But everytime only 1 and 3 are printed. If I put some delay to the 3rd operation than all are printed i.e 1,2,3. Why is it so? Here is my code:
Stream<String> get concatStream => Observable.concat(
[new Observable.just(1.toString()),
new Observable.timer(2.toString(), new Duration(seconds: 1)),
new Observable.just(3.toString())]);
Heya,
Which version of rxdart are you using?
I see 1, 2, 3 in your test,
and I also see 1, 2, 3 if I remove the delay on the second Stream?
Hi @frankpepermans
I am using rxdart: ^0.21.0. I am using StreamBuilder to print the values in a Text widget. I even tried printing the data coming from StreamBuilder snapshot. But it is always printing 1 and 3 with the above setup. I even used the ConcatEagerStream but the results are same. So you think StreamBuilder might have issue?
This configuration is printing all the 3 values. This is weird.
Stream<String> get concatStream => Observable.concat([
new Observable.just(1.toString()),
new Observable.timer(2.toString(), new Duration(seconds: 2)),
new Observable.timer(3.toString(),new Duration(seconds: 1))
]);
Hey there -- I'm not sure we can do much about this from our side. Unfortunately, the Stream is emitting the correct items, but Flutter may not show every single value from the Stream if events come right after the next.
Under the hood, when StreamBuilder receives a new event, it will mark the Widget as needing a rebuild (e.g. run the setState function). However, the timing of these rebuilds may be different than the timing of the data being delivered.
You can see this in the StreamBuilder docs:
/// Widget rebuilding is scheduled by each interaction, using [State.setState],
/// but is otherwise decoupled from the timing of the stream. The [builder]
/// is called at the discretion of the Flutter pipeline, and will thus receive a
/// timing-dependent sub-sequence of the snapshots that represent the
/// interaction with the stream.
Therefore, Flutter will NOT guarantee a rebuild after every item is delivered, but rather when Flutter decides its time to rebuild. Sometimes, this makes it look like a Stream is not delivering values, but in fact Flutter has not been able to render those values between the previous and current build step.
You can verify this behavior using "Pure Streams" and you'll see flutter produces the same behavior: It skips from 1 to 3.
Stream<String> asyncStarStream() async* {
yield "1";
await Future.delayed(Duration(seconds: 1));
yield "2";
yield "3";
}
To fix, you might need to add a small delay if it's critical you see both values.
Awesome! Understood. Thanks for the clarity. @brianegan
Most helpful comment
Hey there -- I'm not sure we can do much about this from our side. Unfortunately, the Stream is emitting the correct items, but Flutter may not show every single value from the Stream if events come right after the next.
Under the hood, when
StreamBuilderreceives a new event, it will mark the Widget as needing a rebuild (e.g. run thesetStatefunction). However, the timing of these rebuilds may be different than the timing of the data being delivered.You can see this in the StreamBuilder docs:
Therefore, Flutter will NOT guarantee a rebuild after every item is delivered, but rather when Flutter decides its time to rebuild. Sometimes, this makes it look like a Stream is not delivering values, but in fact Flutter has not been able to render those values between the previous and current build step.
You can verify this behavior using "Pure Streams" and you'll see flutter produces the same behavior: It skips from
1to3.To fix, you might need to add a small delay if it's critical you see both values.