Last updated:
0 purchases
run once
run_once #
An extremely simple library for running 'things' exactly once. No matter how many times that 'thing' is called.
How does it work? #
Well it's very simple. We basically use the StackTrace.current and carefully use this to keep record on when a function has been called. It means that the call stack is basically used as a unique identifier for when and where a function has been called.
Rationale #
This library could be considered an anti-pattern in itself and a little exercise, but imagine a Flutter StatefulWidget with its build that you cannot rely on being called only when you yourself call setState. In this case you could use runOnce to run something once during this widget's lifetime no matter the times build was called.
Worth a mention; there also is the AsyncMemoizer.runOnce for async functions from package:async but that one isn't aware of the call stack and works internally in a much simpler manner.
Usage #
Pure dart example;
import 'package:run_once/run_once.dart';
void main() async {
/// This will print 'called 1' exactly 1 time although
/// we call this function 10 times.
for (var i = 0; i < 10; i++) {
runOnce(() {
print('called 1');
});
}
/// This will print 'called 2' exactly 2 times as the [runOnce] simply
/// isn't called in the same spot.
runOnce(() {
print('called 2');
});
runOnce(() {
print('called 2');
});
/// This will print 'called 3' exactly 3 times although
/// we call this function 15 times.
/// Note the `forDuration` is exactly a [Duration] of 500 milliseconds.
/// Using `forDuration` means for a duration of 500 milliseconds [runOnce]
/// can only run once.
/// So we loop 15 times in this loop and wait 100 milliseconds in each
/// loop cycle; thus 'called 3' is printed exactly 3 times.
for (var i = 0; i < 15; i++) {
await Future.delayed(Duration(milliseconds: 100));
runOnce(() {
print('called 3');
}, forDuration: Duration(milliseconds: 500));
}
}
copied to clipboard
Flutter with a StatefulWidget example;
import 'package:run_once/run_once.dart';
// This example uses the state_notifier package
class _SomeWidgetState extends State<SomeWidget> {
@override
void dispose() {
/// When this is called [runOnce] will be able to run once again
/// for this class alone.
runOnceDestroy();
super.dispose();
}
@override
Widget build(BuildContext context) {
final state = context.watch<MyState>();
return state.when(
data: () => Placeholder(),
finished: () {
runOnce(() {
/// This is always only called once
/// until [dispose] is called.
Navigator.pushNamed(context, '/b');
});
return Placeholder();
},
);
}
}
copied to clipboard
Disclaimer #
This library isn't really tested very comprehensively at all. So it might not work in every use case.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.