Graham
Graham

Reputation: 5894

Periodic stream not sending data

In my Flutter app, I have a stream created using the Stream.periodic constructor (the timeleft, minutes, and seconds variables are defined in the surrounding context):

_countdown = Stream.periodic(
    Duration(seconds: timeLeft),
    (count) {
        var value = '$minutes : $seconds';
        if (seconds-- == 0) {
            seconds = 59;
            --minutes;
        }
        return value;
    },
);

Then I have a StreamBuilder that consumes the stream:

StreamBuilder<String>(
    stream: _countdown,
    builder: (context, snapshot) {
      String message;
      if (snapshot.connectionState == ConnectionState.done) {
        message = 'Finito!';
      } else {
        message = snapshot.data;
      }

      if(snapshot.hasError)
        message = '${snapshot.error}';

      return Text(
        message ?? 'HOLD',
        style: DefaultTextStyle.of(context)
            .style
            .apply(fontSizeFactor: 3.0),
      );
    },
),

When I run my app, I only see HOLD on the screen, like the snapshot.data variable is null. When I debug my app, the function passed to the Stream.periodic constructor is never called. I have also verified that the timeleft variable is greater than 0. It is actually 360, so the stream should be sending a new value every second and displaying it.

Why are there no values coming through the stream?

EDIT: I accepted diegodeveloper's answer since that was correct. If you would like to see how I ended up implementing the timer with RxDart check my answer below.

Upvotes: 2

Views: 2293

Answers (2)

Graham
Graham

Reputation: 5894

In order to make a timer that stops at a certain time I ended up having to use RxDart and Observables. Here is my solution that creates a stream which emits a value every 1 seconds and stops after a given length of time.

_countdown = Observable.repeat((count) {
    var value = '${hours}h : ${minutes}m : ${seconds}s';

    if (--seconds < 0) {
      seconds = 59;
      --minutes;
    }

    if (minutes < 0) {
      if (hours > 0) {
        minutes = 59;
        --hours;
      } else {
        minutes = 0;
      }
    }

    if (count == 0)
      return Observable.just(value);
    else
      return Observable.timer(value, Duration(seconds: 1));
}, timeLeft + 2);

Upvotes: 0

diegoveloper
diegoveloper

Reputation: 103541

If you check the documentation of the Stream.periodic , you will find this :

Creates a stream that repeatedly emits events at [period] intervals.

So , if you are using 360 seconds as interval, you will have to wait 360 seconds in every change.

Change the timeLeft to one (to emit values every second), change your logic and it should work.

Stream.periodic(
    Duration(seconds: 1),

Upvotes: 1

Related Questions