简体   繁体   English

Flutter 中的持续代码

[英]Persistent Ticker in Flutter

How to get a persistent tick at every frame refresh time.如何在每帧刷新时间获得持久的滴答声。 For example in Flame game engine update method gets called at around every 1/60 seconds and a value dt with elapsed time is passed.例如,在 Flame 游戏引擎中, update方法大约每1/60秒被调用一次,并传递一个带有经过时间的值dt

I want to implement one simple animation where a fan will rotate.我想实现一个简单的 animation 风扇将旋转。 I want to change its rotation speed depending on user input.我想根据用户输入来改变它的旋转速度。 My idea is that at every tick I will rotate the fan image/ container at a fixed value.我的想法是,在每个滴答声中,我都会以固定值旋转扇形图像/容器。 As the user increases the speed I will increase the multiplier.随着用户增加速度,我将增加乘数。 There are few options like using the Flame engine or Flare, but they seem overkill.使用 Flame 引擎或 Flare 之类的选项很少,但它们似乎有点矫枉过正。 Also, I can use SingleTickerProviderMixin but there are few overheads like reverse the animation when finished and forwarded it and so...另外,我可以使用SingleTickerProviderMixin但很少有开销,比如在完成并转发 animation 时反转它等等......

I think there will be a simple solution, which will notify me at each frame refresh time that occurs at around every 1/60 seconds, and pass me the elapsed time dt (around 167 mS or so).我认为会有一个简单的解决方案,它会在大约每 1/60 秒发生的每个帧刷新时间通知我,并将经过的时间dt (大约 167 毫秒左右)传递给我。

A nice way to do it (without Animation widgets), is to implement a Timer with a Stream;一个很好的方法(没有 Animation 小部件)是使用 Stream 实现定时器; see the example below:请参见下面的示例:

import 'package:flutter/material.dart';
import "dart:async";

const frequency = Duration(milliseconds: 50);

void main() => runApp(
      MaterialApp(
        home: Material(
          child: Center(
            child: Container(
              color: Colors.white,
              child: MyWidget(),
            ),
          ),
        ),
      ),
    );

class MyWidget extends StatefulWidget {
  MyWidgetState createState() => MyWidgetState();
}

class MyWidgetState extends State<MyWidget> {
  final StreamController<double> _streamer =
      StreamController<double>.broadcast();

  Timer timer;

  double _rotation = 0.0;

  @override
  void initState() {
    super.initState();

    timer = Timer.periodic(frequency, (t) {
      _rotation++;
      _streamer.add(1);
    });
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<double>(
        initialData: 0,
        stream: _streamer.stream,
        builder: (context, snapshot) {
          return Transform(
            transform: Matrix4.rotationZ(_rotation),
            child: Text('Hello, World!'),
          );
        });
  }
}

I would also make sure to implement the dispose() callback if you copy this code.如果您复制此代码,我还将确保实现 dispose() 回调。 You need to make sure to cancel() any running timers to prevent odd behaviors or they will become a source of memory leaks.您需要确保取消()任何正在运行的计时器以防止奇怪的行为,否则它们将成为 memory 泄漏的来源。

The timer = null;定时器 = null; is not always needed, but there are situations where the state object will hold a reference to the timer var itself and also cause a memory leak.并非总是需要,但在某些情况下 state object 将持有对计时器变量本身的引用,并且还会导致 memory 泄漏。 For example, if you capture the timer var inside the timer callback body.例如,如果您在计时器回调主体中捕获计时器变量。

Example:例子:

@override
  void dispose() {
    timer?.cancel();
    timer = null;
    super.dispose();
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM