播放 rive 动画时在构建期间调用 setState() 或 markNeedsBuild()

时间:2021-07-28 15:02:37

标签: flutter dart rive

在构建期间调用了错误 setState() 或 markNeedsBuild(),而我尝试调用此函数:

void togglePlay() {
    if (_controller == null) {
      return;
    }
    setState(() => _controller.isActive = !_controller.isActive);
  }

当我将它与按钮一起用作 onTap 功能时,不会发生错误。但我只需要调用其他函数。

完整代码如下:

void togglePlay() {
    if (_controller == null) {
      return;
    }
    setState(() => _controller.isActive = !_controller.isActive);
  }

  bool get isPlaying => _controller?.isActive ?? false;
  Artboard _riveArtboard;
  RiveAnimationController _controller;
  // rive

  @override
  void initState() {
    print('guess position');
    // rive
    try {
      rootBundle.load('assets/match.riv').then(
        (data) async {
          final file = RiveFile.import(data);
          final artboard = file.mainArtboard;
          artboard.addController(_controller = SimpleAnimation('Animation 1'));
          _controller.isActive = false;
          setState(() => _riveArtboard = artboard);
        },
      );
    } catch (e) {
      print(e.toString());
    }
    // rive
    super.initState();
  }

  List top = [];
  List left = [];
  List rotation = [];

  next() {
    List correctT = [];
    List correct = [];
    for (int n = 0; n < widget.rotation.length; n++) {
      for (int m = 0; m < widget.rotation.length; m++) {
        if (rotation[m] == widget.rotation[n] &&
            top[m] < widget.top[n] + 45 &&
            top[m] > widget.top[n] - 45 &&
            left[m] < widget.left[n] + 45 &&
            left[m] > widget.left[n] - 45) {
          log('widget match $m qgueals  match $n');
          if (!correctT.contains(n) && !correct.contains(m)) {
            correctT.add(n);
            correct.add(m);
          }
        }
      }
    }
    if (correctT.length == widget.rotation.length) {
      log('nice');
      togglePlay();  // FUNCTION CAUSING ERROR
    }
  }

  nav() {
    SchedulerBinding.instance.addPostFrameCallback((_) {
      Navigator.push(
          context, new MaterialPageRoute(builder: (context) => RandomPos(2)));
    });
  }

  bool created = false;
  createList() {
    if (!created) {
      for (int i = 0; i < widget.top.length; i++) {
        top.add(h - 250);
        left.add(50);
        rotation.add(0);
      }
      setState(() {
        created = true;
      });
    }
  }

  match(int i) {
    return Positioned(
        top: top[i].toDouble(),
        left: left[i].toDouble(),
        child: RotationTransition(
          turns: new AlwaysStoppedAnimation(rotation[i] / 360),
          child: GestureDetector(
            onTap: () {
              rotation[i] = rotation[i] + 45;
              setState(() {});
              next();
            },
            onDoubleTap: () {
              rotation[i] = rotation[i] - 45;
              setState(() {});
              next();
            },
            child: Draggable(
                data: 10,
                onDragUpdate: (details) {
                  top[i] = top[i] + details.delta.dy;
                  left[i] = left[i] + details.delta.dx;
                  setState(() {});
                },
                onDragEnd: next(),
                child: Container(
                  height: 250,
                  width: 250,
                  child: _riveArtboard == null
                      ? const SizedBox()
                      : Rive(artboard: _riveArtboard),
                ),
                feedback: Container()),
          ),
        ));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder(
          future: createList(),
          builder: (context, snapshot) {
            return Container(
              decoration: BoxDecoration(
                  image: DecorationImage(
                      fit: BoxFit.fill,
                      image: AssetImage('wood${widget.wood}.jpg'))),
              child: Stack(
                children: [for (int i = 0; i < rotation.length; i++) match(i)],
              ),
            );
          }),
      floatingActionButton: FloatingActionButton(
          backgroundColor: Colors.white,
          child: Text(
            'next',
            style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
          ),
          onPressed: () => nav()),
    );
  }
}

如果你能看看并帮助我解决,谢谢

典型的“在重建期间调用的设置状态”的一些解决方案不起作用或导致其他错误

1 个答案:

答案 0 :(得分:0)

当我们在构建阶段调用 setState 时会出现此错误。

使用在构建渲染完成后运行的 addPostFrameCallback

void togglePlay() {
  WidgetsBinding.instance.addPostFrameCallback((_) {
    if (_controller == null) {
      return;
    }
    setState(() => _controller.isActive = !_controller.isActive);
  });
}

  Timer.run(() {
    if (_controller == null) {
      return;
    }
    setState(() => _controller.isActive = !_controller.isActive);
  });