flutterdartstreamstream-builderperiodic-task

How to use dynamic interval time in Stream.periodic event in Flutter


I'm struggling to find out a way to emit stream periodically with dynamic interval time in Flutter. I'm not sure, is it really possible or not. One workaround may be canceling the old periodic stream and reinitialize it with a new time interval but my periodic stream with asyncMap doesn't have a cancel option. I could use stream.listen that has cancel method but I purposely need asyncMap to convert the Future event to stream. In this case, what I can do please suggest to me.

My code snippet -

int i = 0;

int getTimeDiffForPeriodicEvent() {
  i++;
  return (_timeDiffBetweenSensorCommands * commandList.length + 1) * i;
}

StreamBuilder(
      stream: Stream.periodic(
              Duration(seconds: maskBloc.getTimeDiffForPeriodicEvent()))
          .asyncMap((_) async => maskBloc.getDataFromMask()),
      builder: (context, snapshot) {
        return Container();
      },
    );

Solution

  • This isn't possible with Stream.periodic, but you could perhaps create a class that can start a stream and sleep based on some mutable variable by using async* and yield:

    class AdjustablePeriodStream {
      Duration period;
      AdjustablePeriodStream(this.period);
    
      Stream<void> start() async* {
        while (true) {
          yield null;
          print('Waiting for $period');
          await Future.delayed(period);
        }
      }
    }
    

    This would allow changing the period fairly easily:

    Future<void> main() async {
      final ten = Duration(milliseconds: 10);
      final twenty = Duration(milliseconds: 20);
      final x = AdjustablePeriodStream(ten);
    
      x.start().take(5).listen((_) {
        print('event!');
        x.period = (x.period == ten ? twenty : ten);
      });
    }
    

    You can see the example output here:

    https://dartpad.dev/6a9cb253fbf29d8adcf087c30347835c

    event!
    Waiting for 0:00:00.020000
    event!
    Waiting for 0:00:00.010000
    event!
    Waiting for 0:00:00.020000
    event!
    Waiting for 0:00:00.010000
    event!
    Waiting for 0:00:00.020000
    

    It just swaps between waiting 10 and 20 milliseconds (presumably you have some other mechanism you want to use for this). You'd probably also want some way to cancel the stream (which would bail out of the while (true) loop) but I ommitted it here to keep the code short and specific.