Flutter 中的持久代码

Posted

技术标签:

【中文标题】Flutter 中的持久代码【英文标题】:Persistent Ticker in Flutter 【发布时间】:2020-08-23 21:17:40 【问题描述】:

如何在每帧刷新时间获得一个持久的滴答声。例如,在 Flame 游戏引擎中,update 方法大约每隔 1/60 秒被调用一次,并传递一个带有经过时间的值 dt。 我想实现一个风扇旋转的简单动画。我想根据用户输入来改变它的旋转速度。我的想法是,在每个滴答声中,我都会以固定值旋转扇形图像/容器。随着用户增加速度,我将增加乘数。使用 Flame 引擎或 Flare 之类的选项很少,但它们似乎有点矫枉过正。另外,我可以使用SingleTickerProviderMixin,但是很少有开销,比如在完成并转发动画时反转动画等等...... 我认为会有一个简单的解决方案,它会在大约每 1/60 秒发生的每一帧刷新时间通知我,并将经过的时间传递给我 dt(大约 167 毫秒)左右)。

【问题讨论】:

AnimationController 是你需要的,更多的是here 如果我使用动画控制器,那么我必须反转和前进动画。我用这个做了一些项目。但是我在问是否有任何简单的解决方案,例如如果存在任何回调类型的东西,颤振会在大约每 1/60 秒左右刷新一次框架(更具体地说是构建方法),以便我可以将我的操作与之同步。 a Ticker - 但如果你准备好使用AnimationController,我真的看不出有任何理由使用这种低级机制@ 所以你建议有一个持续时间为 1 秒的动画控制器,每次我达到 1 秒我都需要反转它?一旦我尝试了 0 毫秒的反向持续时间和 1 秒的正向持续时间,但它给了我一个不可预知的结果。如果你能提供一个极简主义的例子,我可以得到一个持久的滴答声和回调,那就太好了。 ctrl.repeat(); 【参考方案1】:

一个很好的方法(没有动画小部件)是实现一个带流的计时器;请看下面的例子:

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!'),
          );
        );
  

【讨论】:

听起来很有希望,让我检查一下 虽然我认为这不符合问题,但它是提供应用程序范围秒数计数器的有用方法。如果有人为他们的应用程序取消了这个,你应该为状态添加一个 dispose 方法:取消计时器,然后释放它。【参考方案2】:

如果您复制此代码,我也会确保实现 dispose() 回调。您需要确保 cancel() 任何正在运行的计时器以防止出现奇怪的行为,否则它们将成为内存泄漏的来源。

timer = null; 并不总是需要,但在某些情况下,状态对象会持有对 timer var 本身的引用,并且还会导致内存泄漏。例如,如果您在计时器回调主体中捕获计时器变量。

例子:

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

【讨论】:

以上是关于Flutter 中的持久代码的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Web 持久标头

Android Flutter App 中的持久后台工作程序,每 30 秒获取一次 Web API

Flutter 持久化_shared_preferences

Flutter 持久化_shared_preferences

如何在 Flutter 中使用路由制作持久抽屉?

How To - 带有持久子屏幕的 Flutter Drawer