在构建异常期间调用setState()或markNeedsBuild()阻止我执行回调

时间:2019-05-31 02:45:24

标签: flutter dart

当计时器在特定小部件中结束时,我试图执行回调函数,但我不断收到此异常:

  

I / flutter(16413):引发了另一个异常:在构建过程中调用了setState()或markNeedsBuild()。

所以我有一个名为countdown的小部件:

class Countdown extends StatefulWidget {
  final VoidCallback onCountdownExpire;

  Countdown(this.onCountdownExpire);

  @override
  CountdownState createState() => CountdownState();
}

class CountdownState extends State<Countdown> with TickerProviderStateMixin {
  AnimationController controller;

  String get timerString {
    Duration duration = controller.duration * controller.value;
    return '${duration.inMinutes}:${(duration.inSeconds % 60).toString()}';
  }

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    )..addStatusListener((AnimationStatus status){
        if (status == AnimationStatus.completed)
          widget.onCountdownExpire();
    });
    controller.reverse(from: 1.0);
  } 
   ...
   ...
   ... // omitted code
}

因此,一旦动画完成,它将调用回调函数:

class _QuizPageState extends State<QuizPage> {
  ... // omitted code  

  @override
  void initState() {
   ... // omitted code
  }

  void onCountdownExpire() {
    setState(() {
      _topContentImage =  AssetImage(questions[questionNum++].imagePath);
    });
  }
  ... // omitted code
}

我尝试遵循solution,但是它不起作用,并且给了我同样的例外:

  void onCountdownExpire() => 
    setState(() {
      _topContentImage =  AssetImage(questions[questionNum++].imagePath);
    });

我也尝试过此方法,但无济于事:

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    )..addStatusListener((AnimationStatus status) =>
        (status == AnimationStatus.completed) ?
          widget.onCountdownExpire():null
    );
    controller.reverse(from: 1.0);
  }

1 个答案:

答案 0 :(得分:0)

也许尝试包含'dart:async':

import 'dart:async';

然后尝试将对onCountdownExpire函数的调用包装在短暂的Timer()中:

...
        Timer(
          Duration(milliseconds:50),
          () {
            if (status == AnimationStatus.completed)
              widget.onCountdownExpire();
          },
        );
...

这将使setState()发生在动画最后一帧的构建阶段之外。

最有可能发生此错误,因为Countdown()小部件的重绘过程中正在重绘QuizPage()。添加Timer()将迫使更新以异步方式在build()范围之外进行,并且仍将获得相同的结果而不会出错。