Flutter 中的持久性代码
Persistent Ticker in Flutter
如何在每个帧刷新时间获得持久的滴答声。例如,在 Flame 游戏引擎中,update
方法大约每 1/60
秒调用一次,并传递一个带有经过时间的值 dt
。
我想实现一个风扇旋转的简单动画。我想根据用户输入改变它的旋转速度。我的想法是,在每次滴答时,我都会以固定值旋转风扇图像/容器。当用户提高速度时,我会增加乘数。使用 Flame 引擎或 Flare 之类的选项很少,但它们似乎有点过分了。另外,我可以使用 SingleTickerProviderMixin
但是很少有开销,比如完成后反转动画并转发等等......
我认为会有一个简单的解决方案,它会在大约每 1/60 秒发生的每个帧刷新时间通知我,并将经过的时间 dt
(大约 167 毫秒左右)传给我).
一个很好的方法(没有 Animation 小部件)是用 Stream 实现 Timer;请参阅下面的示例:
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() 回调。您需要确保取消 () 任何 运行 计时器以防止奇怪的行为,否则它们将成为内存泄漏的来源。
timer = null;并不总是需要的,但在某些情况下,状态对象将持有对计时器 var 本身的引用,也会导致内存泄漏。例如,如果您在定时器回调主体中捕获定时器变量。
示例:
@override
void dispose() {
timer?.cancel();
timer = null;
super.dispose();
}
如何在每个帧刷新时间获得持久的滴答声。例如,在 Flame 游戏引擎中,update
方法大约每 1/60
秒调用一次,并传递一个带有经过时间的值 dt
。
我想实现一个风扇旋转的简单动画。我想根据用户输入改变它的旋转速度。我的想法是,在每次滴答时,我都会以固定值旋转风扇图像/容器。当用户提高速度时,我会增加乘数。使用 Flame 引擎或 Flare 之类的选项很少,但它们似乎有点过分了。另外,我可以使用 SingleTickerProviderMixin
但是很少有开销,比如完成后反转动画并转发等等......
我认为会有一个简单的解决方案,它会在大约每 1/60 秒发生的每个帧刷新时间通知我,并将经过的时间 dt
(大约 167 毫秒左右)传给我).
一个很好的方法(没有 Animation 小部件)是用 Stream 实现 Timer;请参阅下面的示例:
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() 回调。您需要确保取消 () 任何 运行 计时器以防止奇怪的行为,否则它们将成为内存泄漏的来源。
timer = null;并不总是需要的,但在某些情况下,状态对象将持有对计时器 var 本身的引用,也会导致内存泄漏。例如,如果您在定时器回调主体中捕获定时器变量。
示例:
@override
void dispose() {
timer?.cancel();
timer = null;
super.dispose();
}