Flutter中使用Timer及cancel()方法的执行异常问题
问题分析与解决
首先要纠正一个误解:timer.cancel()只会终止Timer的周期性回调,并不会终止后续代码的执行。你看不到This comes afterwards的核心原因是对Dart的异步执行顺序理解有误,再加上可能的日志输出问题。
为什么输出顺序和你预期的不一样?
Dart的代码执行遵循事件循环机制:
- 同步代码会被优先执行:你创建
Timer.periodic的操作是同步的,但Timer的回调函数是异步任务,会被放到事件队列中等待处理。 - 所以
developer.log('This comes afterwards')这行同步代码,会在Timer的任何一次回调触发之前就执行完毕。它的输出应该出现在所有Timer日志的最顶部,而不是你预期的最后。
为什么你没看到这行日志?
大概率是这两种情况:
- 输出顺序没注意到:它其实已经打印了,只是在日志的最开头,你可能没留意到;
developer.log的输出被过滤:developer.log默认受日志级别和系统配置影响,有时候会被控制台过滤。你可以换成print()来测试,它的输出更直接,不容易被过滤。
如果你想在Timer结束后执行代码
如果你的真实需求是在Timer完成(调用cancel后)再执行后续代码,那应该把代码放到Timer的回调函数内部,紧跟在timer.cancel()之后:
var counter = 0; Timer.periodic(const Duration(milliseconds: 50), (timer) { print('Actual counter ' + counter.toString()); counter++; if (counter == 5) { print('TIMER DONE'); timer.cancel(); print('This comes afterwards'); // 这里会在Timer结束后执行 } });
如果你只是想看到原代码的日志输出
把developer.log换成print(),同时注意观察输出顺序:
import 'dart:async'; void main() { var counter = 0; Timer.periodic(const Duration(milliseconds: 50), (timer) { print('Actual counter ' + counter.toString()); counter++; if (counter == 5) { print('TIMER DONE'); timer.cancel(); } }); print('This comes afterwards'); // 这行会先打印 }
这段代码的正确输出顺序应该是:
This comes afterwards Actual counter 0 Actual counter 1 Actual counter 2 Actual counter 3 Actual counter 4 TIMER DONE
内容的提问来源于stack exchange,提问作者Heady
相关产品推荐
相关产品推荐

