Timers in flutter behave differently than expected.
If I call a specific function for each cycle in millisecond units,
it may lag behind the cycle.
Even if I tested only timers without other code, it did.
When I tested with other code, the degree of delay became severe.
It would be okay if does delay stays at ~99 milliseconds,
However it jumps to 100~1000 milliseconds if i use timer in my application.
I tested with Timer(dart:async), Metronome(Quiver library), Timer(dart:async) in Isolate.
An interesting phenomenon is, when i set those timers with same period and started,
those timers delays similar duration at similar moment.
For example, when I tested those timers in my application code, those three delays 1000 milliseconds at the same time. (large usage of memory ?)
Below is the test code. I'm testing on Galaxy Tab S4.(real device)
How can i use timer in milliseconds units?
//code for isolate
DateTime lastIsolate;
DateTime currentIsolate;
int isolateCounter = 0;
void timerTest(SendPort sendPort){
print("Start Timer");
lastIsolate = DateTime.now();
Timer timer = Timer.periodic(Duration(milliseconds: 20), checkTimerPeriod);
ReceivePort receivePort = ReceivePort();
sendPort.send(receivePort.sendPort);
receivePort.listen((message){
if(message is bool){
timer.cancel();
}
});
}
void checkTimerPeriod(Timer timer){
currentIsolate = DateTime.now();
Duration diff = currentIsolate.difference(lastIsolate);
if(diff.inMilliseconds > 30){
isolateCounter++;
print("${DateTime.now()}] Isolate :: ${diff.inMilliseconds}, $isolateCounter times");
}
lastIsolate = currentIsolate;
}
void main() {
ensureInitializedForSharedPreference();
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight]) ;
runApp(MyApp());
}
void ensureInitializedForSharedPreference(){
WidgetsFlutterBinding.ensureInitialized() ;
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp>{
Isolate isolate;
ReceivePort _receivePort = ReceivePort();
DateTime _lastTimer;
DateTime _currentTimer;
DateTime _lastMetronome;
DateTime _currentMetronome;
Timer timer;
StreamSubscription<DateTime> metronome;
int timerCounter;
int metronomeCounter;
@override
void initState() {
super.initState();
timerCounter = 0;
metronomeCounter = 0;
startTimers();
spawnIsolate();
}
void startTimers(){
_lastTimer = DateTime.now();
_lastMetronome = DateTime.now();
timer = Timer.periodic(Duration(milliseconds: 20), timerCheck) ;
metronome = Metronome.epoch(aMillisecond * 20).listen((event) {
metronomeCheck();
});
}
void timerCheck(Timer timer){
_currentTimer = DateTime.now();
Duration diff = _currentTimer.difference(_lastTimer);
if(diff.inMilliseconds > 30){
timerCounter++;
print("${DateTime.now()}] Timer :: ${diff.inMilliseconds}, $timerCounter times");
}
_lastTimer = _currentTimer;
}
void metronomeCheck(){
_currentMetronome = DateTime.now();
Duration diff = _currentMetronome.difference(_lastMetronome);
if(diff.inMilliseconds > 30){
metronomeCounter++;
print("${DateTime.now()}] Metronome :: ${diff.inMilliseconds}, $metronomeCounter times");
}
_lastMetronome = _currentMetronome;
}
void spawnIsolate() async {
isolate = await Isolate.spawn(timerTest, _receivePort.sendPort);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
debugShowCheckedModeBanner: false,
home: TimerTestPage()
// home: MyHomePage(),
);
}
}
class TimerTestPage extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return TimerTestPageState();
}
}
class TimerTestPageState extends State<TimerTestPage>{
@override
Widget build(BuildContext context) {
return Container();
}
}
Print Result:
I/flutter (11728): 2020-11-18 18:00:54.002557] Metronome :: 99, 2 times
I/flutter (11728): 2020-11-18 18:00:54.002805] Timer :: 91, 2 times
I/flutter (11728): 2020-11-18 18:00:54.137470] Timer :: 45, 3 times
I/flutter (11728): 2020-11-18 18:00:54.137680] Metronome :: 35, 3 times
I/flutter (11728): 2020-11-18 18:00:54.456208] Metronome :: 34, 4 times
I/flutter (11728): 2020-11-18 18:00:55.063127] Metronome :: 38, 5 times
I/flutter (11728): 2020-11-18 18:00:55.108351] Timer :: 37, 4 times
I/flutter (11728): 2020-11-18 18:00:55.209915] Metronome :: 67, 6 times
I/flutter (11728): 2020-11-18 18:00:55.210140] Timer :: 56, 5 times
I/flutter (11728): 2020-11-18 18:00:58.800702] Metronome :: 49, 7 times
I/flutter (11728): 2020-11-18 18:00:58.801505] Timer :: 50, 6 times
I/flutter (11728): 2020-11-18 18:00:58.845783] Isolate :: 49, 2 times
I/flutter (11728): 2020-11-18 18:00:59.838194] Timer :: 40, 7 times
I/flutter (11728): 2020-11-18 18:00:59.838950] Metronome :: 35, 8 times
I/flutter (11728): 2020-11-18 18:01:00.835309] Metronome :: 52, 9 times
I/flutter (11728): 2020-11-18 18:01:00.837709] Timer :: 44, 8 times
I/flutter (11728): 2020-11-18 18:01:01.779771] Metronome :: 37, 10 times
I/flutter (11728): 2020-11-18 18:01:02.802442] Metronome :: 59, 11 times
I/flutter (11728): 2020-11-18 18:01:02.803132] Timer :: 51, 9 times
I/flutter (11728): 2020-11-18 18:01:02.827479] Isolate :: 31, 3 times
I/flutter (11728): 2020-11-18 18:01:03.800940] Metronome :: 52, 12 times
I/flutter (11728): 2020-11-18 18:01:03.801845] Timer :: 49, 10 times
I/flutter (11728): 2020-11-18 18:01:03.835860] Isolate :: 39, 4 times
I/flutter (11728): 2020-11-18 18:01:04.860201] Timer :: 66, 11 times
I/flutter (11728): 2020-11-18 18:01:04.860752] Metronome :: 57, 13 times
I/flutter (11728): 2020-11-18 18:01:04.871719] Isolate :: 35, 5 times
I/flutter (11728): 2020-11-18 18:01:05.797080] Metronome :: 54, 14 times
I/flutter (11728): 2020-11-18 18:01:05.798653] Timer :: 46, 12 times
I/flutter (11728): 2020-11-18 18:01:06.798412] Metronome :: 51, 15 times
I/flutter (11728): 2020-11-18 18:01:06.799347] Timer :: 47, 13 times
I/flutter (11728): 2020-11-18 18:01:07.802850] Metronome :: 52, 16 times
I/flutter (11728): 2020-11-18 18:01:07.803528] Timer :: 52, 14 times
I/flutter (11728): 2020-11-18 18:01:07.832428] Isolate :: 36, 6 times
I/flutter (11728): 2020-11-18 18:01:08.798311] Metronome :: 56, 17 times
I/flutter (11728): 2020-11-18 18:01:08.802467] Timer :: 50, 15 times
I/flutter (11728): 2020-11-18 18:01:09.810389] Timer :: 58, 16 times
I/flutter (11728): 2020-11-18 18:01:09.811026] Metronome :: 48, 18 times
I/flutter (11728): 2020-11-18 18:01:09.835066] Isolate :: 38, 7 times
I/flutter (11728): 2020-11-18 18:01:10.810530] Metronome :: 65, 19 times
I/flutter (11728): 2020-11-18 18:01:10.812136] Timer :: 60, 17 times
I/flutter (11728): 2020-11-18 18:01:10.830197] Isolate :: 34, 8 times
I/flutter (11728): 2020-11-18 18:01:11.810372] Timer :: 48, 18 times
I/flutter (11728): 2020-11-18 18:01:11.810956] Metronome :: 48, 20 times
I/flutter (11728): 2020-11-18 18:01:11.826718] Isolate :: 31, 9 times
I/flutter (11728): 2020-11-18 18:01:12.802337] Timer :: 50, 19 times
I/flutter (11728): 2020-11-18 18:01:12.810522] Metronome :: 47, 21 times
I/flutter (11728): 2020-11-18 18:01:12.841223] Isolate :: 44, 10 times
I/flutter (11728): 2020-11-18 18:01:13.631729] Timer :: 36, 20 times
I/flutter (11728): 2020-11-18 18:01:13.801782] Metronome :: 58, 22 times
I/flutter (11728): 2020-11-18 18:01:13.802542] Timer :: 50, 21 times
I/flutter (11728): 2020-11-18 18:01:13.835463] Isolate :: 39, 11 times
I/flutter (11728): 2020-11-18 18:01:14.789602] Timer :: 35, 22 times
I/flutter (11728): 2020-11-18 18:01:15.754015] Metronome :: 31, 23 times
I/flutter (11728): 2020-11-18 18:01:15.811248] Isolate :: 35, 12 times
I/flutter (11728): 2020-11-18 18:01:16.753175] Timer :: 36, 23 times
I/flutter (11728): 2020-11-18 18:01:16.787876] Metronome :: 33, 24 times
I/flutter (11728): 2020-11-18 18:01:16.791421] Timer :: 34, 24 times
I/flutter (11728): 2020-11-18 18:01:17.839036] Metronome :: 55, 25 times
I/flutter (11728): 2020-11-18 18:01:17.842928] Timer :: 51, 25 times
I/flutter (11728): 2020-11-18 18:01:17.871998] Isolate :: 35, 13 times
I/flutter (11728): 2020-11-18 18:01:18.804048] Timer :: 52, 26 times
I/flutter (11728): 2020-11-18 18:01:18.804922] Metronome :: 41, 26 times
I/flutter (11728): 2020-11-18 18:01:18.836156] Isolate :: 39, 14 times
I/flutter (11728): 2020-11-18 18:01:19.796440] Metronome :: 45, 27 times
I/flutter (11728): 2020-11-18 18:01:19.797077] Timer :: 45, 27 times
I/flutter (11728): 2020-11-18 18:01:20.755218] Metronome :: 31, 28 times
I/flutter (11728): 2020-11-18 18:01:20.794793] Timer :: 37, 28 times
I/flutter (11728): 2020-11-18 18:01:20.798211] Metronome :: 36, 29 times
I/flutter (11728): 2020-11-18 18:01:21.803089] Metronome :: 59, 30 times
I/flutter (11728): 2020-11-18 18:01:21.803601] Timer :: 51, 29 times
I/flutter (11728): 2020-11-18 18:01:22.283024] Timer :: 32, 30 times
I/flutter (11728): 2020-11-18 18:01:22.755033] Metronome :: 31, 31 times
I/flutter (11728): 2020-11-18 18:01:22.790614] Metronome :: 35, 32 times
I/flutter (11728): 2020-11-18 18:01:22.794945] Timer :: 38, 31 times
I/flutter (11728): 2020-11-18 18:01:22.815671] Isolate :: 39, 15 times
I/flutter (11728): 2020-11-18 18:01:23.163503] Timer :: 31, 32 times
I/flutter (11728): 2020-11-18 18:01:23.795069] Metronome :: 51, 33 times
I/flutter (11728): 2020-11-18 18:01:23.795837] Timer :: 43, 33 times
I/flutter (11728): 2020-11-18 18:01:23.841426] Isolate :: 43, 16 times
I/flutter (11728): 2020-11-18 18:01:24.795185] Metronome :: 49, 34 times
I/flutter (11728): 2020-11-18 18:01:24.795927] Timer :: 44, 34 times
I/flutter (11728): 2020-11-18 18:01:25.804665] Timer :: 52, 35 times
I/flutter (11728): 2020-11-18 18:01:25.805359] Metronome :: 41, 35 times
I/flutter (11728): 2020-11-18 18:01:25.831298] Isolate :: 35, 17 times
I/flutter (11728): 2020-11-18 18:01:26.806900] Metronome :: 39, 36 times
I/flutter (11728): 2020-11-18 18:01:26.807681] Timer :: 35, 36 times
I/flutter (11728): 2020-11-18 18:01:26.832718] Isolate :: 36, 18 times
From the Timer.periodic
documentation:
The exact timing depends on the underlying timer implementation. No more than n callbacks will be made in duration * n time, but the time between two consecutive callbacks can be shorter and longer than duration.
The Timer
in dart isn't intended to be as accurate as you seem to be expecting.