Rxdart: Observable concat operator not printing all values

Created on 24 Mar 2019  路  4Comments  路  Source: ReactiveX/rxdart

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())]);

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 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.

All 4 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

x4080 picture x4080  路  4Comments

SAGARSURI picture SAGARSURI  路  9Comments

qiangjindong picture qiangjindong  路  3Comments

egorikem picture egorikem  路  8Comments

PritishSawant picture PritishSawant  路  3Comments