在我StatelessWidget岁的时候,我有一个周期性计时器.这里是一段生成计时器的代码,不需要太多细节:

class AnniversaryHomePage extends StatelessWidget {

  . . .  

  void _updateDisplayTime(StoreInheritedWidget inheritedWidget) {
    String anniversaryString = inheritedWidget.prefs.getString('anniversaryDate');
    inheritedWidget.store.dispatch(DateTime.parse(anniversaryString));
  }

  /// Widget Methods
  @override
  Widget build(BuildContext context) {
    final inheritedWidget = StoreInheritedWidget.of(context);
    new Timer.periodic(this.refreshRate, (Timer timer) => _updateDisplayTime(inheritedWidget));

    . . .
}

当我try 将应用程序的起始点输入flutter test时,得到以下错误消息:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test:
A periodic Timer is still running even after the widget tree was disposed.
'package:flutter_test/src/binding.dart': Failed assertion: line 668 pos 7:
'_fakeAsync.periodicTimerCount == 0'

问题是,我用错了我的Timer.periodic美元吗?如果没有,我如何减轻此错误?

推荐答案

问题是,创建计时器会创建一个必须释放的资源,因此您的小部件实际上是有状态的,而不是无状态的.具体地说,build方法可以每秒调用60次(如果平台为120fps,则调用次数可以更多).任何不足都只是一种优化.

您的代码中有一个非常严重的错误-build方法每次被调用时都会创建一个新计时器.而且,由于您的计时器从未取消,您可能会有数百甚至数千个事件被分派到您的store .

为了避免这种情况,该框架有一个State类,生命周期为initStatedispose.该框架promise ,如果它重建了你的小部件,它不会多次调用initState,而且总是调用dispose.这允许您创建一次计时器,并在随后的build调用中重用它.

例如,您可以将大部分逻辑移到州,如下所示.在小部件上保留REFREHRATE,您甚至可以使用didUpdateWidget生命周期取消和更新您的计时器.

class AnniversaryHomePage extends StatefulWidget {
  @override
  State createState() => new AnniversaryHomePageState();
}

class AnniversaryHomePageState extends State<AnniversaryHomePage> {
  Timer _timer;

  @override
  void initState() {
    _timer = new Timer.periodic(widget.refreshRate, 
      (Timer timer) => _updateDisplayTime(inheritedWidget));
    super.initState();
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    ...
  }
}

Dart相关问答推荐

具有级联省道的三元算子的奇异行为

?? ("if null") 运算符类型解析问题

Dart 扩展: don't access members with "this" unless avoiding shadowing

使用 2 个类型参数声明类型StateNotifierProvider,但给出了 1 个类型参数

如何在 Dart 游戏中重复听按键?

创建默认应用时 FirebaseOptions 不能为空

Asset图像作为Card背景,Flutter 中顶部有文本

Flutter - 在 null 上调用了 getter 'length'

如何在 Flutter/dart 中获取一周中特定日期的日期?

如何使用 StreamBuilder 更新 TextField 的值?

在 Dart 中将对象推入数组

Dart-对base64字符串进行编码和解码

如何实现从左侧滑动的侧边菜单?

Firebase 手机身份验证Flutter crash崩溃

如何在 showModalBottomSheet 中设置状态

Dart 交互/访问数据库

在 Dart 中切换失败

dart 中隐式转换运算符的语法是什么?

用于 dartlang 的 REPL

如何使用 Dart 将字符串解析为数字?