versatile_timer 1.0.1 copy "versatile_timer: ^1.0.1" to clipboard
versatile_timer: ^1.0.1 copied to clipboard

VersatileTimer is designed to support many use cases where a stream of timed events is required. In addition to start, stop, pause, resume and changeSpeed, VersatileTimer offers a number of options t [...]

VersatileTimer #

VersatileTimer is designed to support many use cases where a stream of timed events is required.

It offers a set of common functionality, plus a number of options to determine how the output 'ticks' are generated from a given input.

Common Functionality #

  • Timer start, stop, pause and resume
  • Configurable 'tick' interval
  • Speed change (that is, changing the tick interval) while running
  • Listeners for the timer state
  • User definable transformers to modify an input prior to output, or mute it (prevent its output)
  • A single configuration may be repeated n times, or run continuously.

Specific Functionality #

These options are provided by different implementations of TickFilter and currently support these broad categories.

  • Fixed input FixedInputFilter: A single input value is defined by the user
  • Data input: IndexedFilter: A list of data is supplied by the user, and the tick count used as an index to look up the data
  • Pattern input: PatternFilter: A user supplied configuration defines a pattern, and the output is generated from that pattern. This is a very flexible method of providing a structured output from a static input.

Note that all of these support the use of a transformer to modify the input, and/or mute selected ticks, thereby preventing them from being output.

Usage #

To monitor the output of the timer you can use something like this:

class ExampleMonitor<IN, OUT> {
  ExampleMonitor(this.timer);

  final VersatileTimer<IN, OUT> timer;
  int count = 0;

  void monitor(Stream<OUT> stream) {
    stream.listen((data) {
      count++;
      // ignore: noop_primitive_operations
      print(data.toString());
    });
  }
}

Fixed Input #

To generate a stream of 100 'ticks' at 10ms intervals, where each tick is the current $count. Output ony those where $count is an odd number - thus the output will actually only be 50 ticks, each at 20ms intervals. The inputValue is irrelevant here, because the transformer does not use it, but would often be used as part or all of the output.

class OddNumbersOnly implements FixedTransform<int, int> {
  @override
  int? transform({required int count, required int input}) {
    final int r = count % 2;
    return r == 0 ? null : count;
  }
}

Future<void> main() async {
  final timer = FixedTimer<String, String>(
    tickInterval: const Duration(milliseconds: 10),
    inputValue: 1,
    maxTicks: 100,
    transformer: OddNumbersOnly(),
  );
  final monitor = ExampleMonitor<String, String>(timer);
  monitor.monitor(timer.output);
  await timer.start();
  await timer.waitUntilFinished();
}

Data Input #

Lookup from a list of data, and output a tick every 100ms containing the data element. No transformer is needed here, as we are just transferring the input data to the output. This method is useful, for example, for drawing a chart in slow motion.

Future<void> main() async {
  final timer = IndexedTimer<Data, Data>(
    data: const [
      Data(quantity: 1, product: 'a'),
      Data(quantity: 2, product: 'b'),
      Data(quantity: 3, product: 'c'),
    ],
    tickInterval: const Duration(milliseconds: 100),
  );
  final monitor = ExampleMonitor<Data, Data>(timer);
  monitor.monitor(timer.output);
  await timer.start();
  await timer.waitUntilFinished();
}

Pattern Input #

Generate a pattern of integers like this: 1,1,3,3,3,3,1,1,3,3,3,3

This relies heavily on the repeat property of each step.

Complex patterns be defined by using nestable Groups, potentially creating a deeply nested pattern. See example/pattern_example.dart

Future<void> main() async {
  final timer = WeightedTimer<int>(
    tickInterval: const Duration(milliseconds: 100),
    config: const WeightedConfig(
      repeat: 2,
      pattern: [
        Weight(1, repeat: 2, label: 'step 1'),
        Weight(3, repeat: 4),
      ],
    ),
    transformer: const WeightValueTransformer(),
  );
  final monitor = ExampleMonitor<Weight, int>(timer);
  monitor.monitor(timer.output);
  await timer.start();
  await timer.waitUntilFinished();
}

Waiting to Complete #

A timer may be set to run continuously, by setting its continuous property to true. It would then run until the [stop] or [pause] method is called.

If continuous is false, then the timer will run until either [maxTicks] is reached, or in the case of the IndexedTimer, the data runs out.

Depending on your use case, you can use one of these to await a particular completion state:

  • await timer.waitUntilFinished(): This will wait until the timer reaches a [TimerState.finished] state. This occurs only when a natural finish is reached, when all [repeat]s of all [maxTicks] is completed. It does NOT occur when the [stop] method is called.
  • await timer.waitUntilStopped(): This will wait until the timer reaches a [TimerState.stopped] state. This occurs only when the [stop] method is called.
  • await timer.waitUntilDone: This will wait until the timer reaches either a [TimerState.finished] or a [TimerState.stopped] is reached.

Examples #

See the examples tab, and the 'example' directory.

Contributions #

  • Usage examples would be especially welcome, just a brief description of how you use the library would be great
  • Code contributions are welcome, provided they include unit tests.
0
likes
130
pub points
0%
popularity

Publisher

verified publishertakkan.org

VersatileTimer is designed to support many use cases where a stream of timed events is required. In addition to start, stop, pause, resume and changeSpeed, VersatileTimer offers a number of options to determine how the output 'ticks' are generated from a given input.

Repository (GitLab)
View/report issues

Documentation

API reference

License

BSD-3-Clause (LICENSE)

Dependencies

logger

More

Packages that depend on versatile_timer