darttimercallbackmessage-passing

Dart callback - passing asynchronous message to parent object


I am trying to pass data (bool) from a child class through a callback Function (ondone) provided by the parent class, which will be called in a periodic function with a boolean argument.

import 'dart:async';

class Flow {
  MyTimer timer;
  bool done = false;
  Function ondone;

  Flow() {
    ondone = (bool b) => done=b;
  }

  void addtimer(int t) {
    timer = MyTimer(t, ondone);
  }

}

class MyTimer {
  final int time;
  int remaining;
  Function callback;
  Timer _timer;

  MyTimer(this.time, this.callback){
    remaining = time;
  }

  void run() {
    _timer = Timer.periodic(
        Duration(seconds: 1), 
        (t) { 
          remaining--;
          if (remaining == 0) {
          _timer.cancel();
          callback(true);
    }
    });
  }
}

But I am unable to figure out if callback is being called or not, because print function (in main) is not printing anything which is wrapped in an if expression.

void main() {
  var flow=Flow();
  flow.addtimer(5);
  flow.timer.run();
  if(flow.done) print('Timer Finished..');
  print('I need to run while timer is working');
}

Passing data from child to parent in an imperative style is important for me (as a beginner).


Solution

  • The call to flow.timer.run() invokes the Timer which executes asynchronously. Your next line of code tests flow.done immediately, and of course it is not done yet. If you do this:

      flow.timer.run();
      await Future.delayed(Duration(seconds: 6));
      if (flow.done) print('Timer Finished..');
    

    Then your main function will pause for 6 seconds by which time the Timer will be complete.

    If you do want to wait for the delay, you could code as follows:

      Future<void> run() async {
        while (remaining > 0) {
          await Future.delayed(Duration(seconds: 1));
          remaining = remaining - 1;
        }
        callback(true);
      }
    

    and call it as:

      await flow.timer.run();
    

    Edit: If you want to run other code in main and then wait, you can do:

      var future = flow.timer?.run();
      print('Timer is running...');
      await future;
      if (flow.done) print('Timer Finished..');