【发布时间】:2021-10-08 21:11:20
【问题描述】:
看看...
文件:dashboard.dart
// @dart=2.8
import 'package:flutter/material.dart';
import 'package:myApp/Pages/Dashboard/widgets/Episodes/episodes.dart';
class DashboardPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final double scrWidth = MediaQuery.of(context).size.width; // if I comment this line, this will work !!!!
return Container(child: EpisodesWidget());
}
}
文件:episode.dart
// @dart=2.8
import 'package:flutter/material.dart';
class EpisodesWidget extends StatefulWidget {
String nowPlaying = "";
@override
_EpisodesWidgetState createState() => _EpisodesWidgetState();
}
class _EpisodesWidgetState extends State<EpisodesWidget> {
void play(String file) async {
if (file == widget.nowPlaying) {
setState(() {
widget.nowPlaying = "";
});
}
setState(() {
widget.nowPlaying = file;
});
return;
}
@override
Widget build(BuildContext context) {
return Column(children: [
RowWidget(
key: UniqueKey(),
id: '1111',
currentPlaying: widget.nowPlaying,
onPlay: (value) => play(value)),
]);
}
}
class RowWidget extends StatefulWidget {
final String id;
final String currentPlaying;
final ValueChanged onPlay;
RowWidget({this.id, this.currentPlaying, this.onPlay, Key key})
: super(key: key);
@override
_RowWidgetState createState() => _RowWidgetState();
}
class _RowWidgetState extends State<RowWidget> {
@override
Widget build(BuildContext context) {
return Container(
child: GestureDetector(
onTap: () => widget.onPlay(widget.id + '.mp3'),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Icon(
widget.currentPlaying == widget.id + '.mp3'
? Icons.pause_circle
: Icons.play_circle,
color: widget.currentPlaying == widget.id + '.mp3'
? Colors.grey
: Color(0xFFFF8117e),
size: 25,
),
),
));
}
}
这个例子只是一个简单的例子:当你点击它时,这将在播放和暂停图标之间切换
这确实有效,但是如果我调整屏幕大小,则会回到初始状态。
所以,一个测试是:
- 使用 Chrome 执行
- 按下播放按钮(这将成为暂停按钮)
- 现在调整屏幕大小
- 暂停按钮恢复为播放按钮,只是因为我调整了屏幕大小
如果我评论该行
final double scrWidth = MediaQuery.of(context).size.width;
这将按预期工作。变量scrWidth 未被使用。因此,仅使用媒体查询对该变量进行简单分配就会导致非常奇怪的行为。
有人可以帮助我吗?这是颤振错误吗?我是 Flutter 的新手,所以也许我必须以错误的方式做事。这是什么原因?我该如何解决?
根据一位同事的建议,将所有内容更改为有状态,我将文件 dashboard.dart 设置为:
import 'package:flutter/material.dart';
import 'package:...episodes.dart';
class DashboardPage extends StatefulWidget {
@override
_DashboardPageState createState() => _DashboardPageState();
}
class _DashboardPageState extends State<DashboardPage> {
@override
Widget build(BuildContext context) {
final double scrWidth = MediaQuery.of(context).size.width;
return Container(child: EpisodesWidget());
}
}
但我仍然面临同样的问题。
【问题讨论】:
-
MediaQuery 不会重置任何内容...调整屏幕大小会调用再次使用的每个构建方法以获取新的屏幕值。 EpisodesWidget() 它被一遍又一遍地创建,使其无法保持状态。你需要改变你的逻辑或者让一切都变成有状态的。
-
用
LayoutBuilder代替怎么样? -
@YeasinSheikh,此代码是场景的最小版本 - 仅用于说明问题。整个项目都有很多这样的情况。所以我正在寻找解决方案或者解释。不过谢谢!无论如何,我都会研究 Layour Builder。
-
我明白,不用他居高临下。每次调用 build 方法时都会调用 MediaQuery,这就是继承小部件的工作方式,调用 MediaQuery 内部的变量将请求新的窗口大小信息并通知渲染树。我建议您阅读 Flutter 渲染树的工作原理。
-
@MarianoZorrilla 您的第一条评论不正确。问题是他们忽略了分析器警告并试图将状态存储在
StatefulWidget而不是State中。无需更改任何逻辑并使任何其他小部件有状态。仅仅因为EpisodesWidget被一遍又一遍地创建并不意味着它的状态正在被破坏。
标签: flutter dart flutter-web