setState 不更新用户界面
setState doesn't update the user interface
我在使用 Stateful Widgets 时遇到了一些与 setState 函数相关的问题,这些 Stateful Widgets 在定时器的帮助下自我更新。下面的代码显示了 2 个 main 类,它们复制了我是如何发现这个错误的。文本小部件 "Lorem" 应在 10 秒内插入 - 它是 - 但从未显示。我尝试调试数组 "Items" 并且它 确实 在 5 秒后包含 "lorem" 文本小部件,这是应该的。 "build" 函数运行但在 UI.
中没有任何区别
class textList extends StatefulWidget {
@override
State<StatefulWidget> createState() =>
new _textListState();
}
class _textListState extends State<textList>
with TickerProviderStateMixin {
List<Widget> items = new List();
Widget lorem = new textClass("Lorem");
Timer timer;
@override
void initState() {
super.initState();
items.add(new textClass("test"));
items.add(new textClass("test"));
timer = new Timer.periodic(new Duration(seconds: 5), (Timer timer) {
setState(() {
items.removeAt(0);
items.add(lorem);
});
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
Iterable<Widget> content = ListTile.divideTiles(
context: context, tiles: items).toList();
return new Column(
children: content,
);
}
}
class textClass extends StatefulWidget {
textClass(this.word);
final String word;
@override
State<StatefulWidget> createState() =>
new _textClass(word);
}
class _textClass extends State<textClass>
with TickerProviderStateMixin {
_textClass(this.word);
String word;
Timer timer;
@override
void initState() {
super.initState();
timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) {
setState(() {
word += "t";
});
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
return new Text(word);
}
}
这不是我发现此错误的方式,但这是复制它的最简单方法。主要思想是:子文本应不断更新自己(在本例中,最后添加 "t"s),5 秒后,应将最后一个文本替换为文本小部件 "Lorem" ,列表中发生了什么,但 UI.
中没有
这是错误的地方:
- A
State
不应该有任何构造函数参数。使用 widget
属性 获取关联 StatefulWidget
. 的最终属性
- Flutter 正在重用您的
_textClass
实例,因为 class 名称和键匹配。这是一个问题,因为您只在 initState
中设置了 widget.word
,所以您没有获取新的 word
配置信息。您可以通过为 StatefulWidget
实例提供唯一的键来消除它们的歧义并导致旧的 State
被处理来解决这个问题,或者您可以保留旧的 State
并实现 didUpdateWidget
.后一种方法如下所示。
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new Scaffold(
appBar: new AppBar(title: new Text('Example App')),
body: new textList(),
),
));
}
class textList extends StatefulWidget {
@override
State<StatefulWidget> createState() =>
new _textListState();
}
class _textListState extends State<textList>
with TickerProviderStateMixin {
List<Widget> items = new List();
Widget lorem = new textClass("Lorem");
Timer timer;
@override
void initState() {
super.initState();
items.add(new textClass("test"));
items.add(new textClass("test"));
timer = new Timer.periodic(new Duration(seconds: 5), (Timer timer) {
setState(() {
items.removeAt(0);
items.add(lorem);
});
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
Iterable<Widget> content = ListTile.divideTiles(
context: context, tiles: items).toList();
return new Column(
children: content,
);
}
}
class textClass extends StatefulWidget {
textClass(this.word);
final String word;
@override
State<StatefulWidget> createState() =>
new _textClass();
}
class _textClass extends State<textClass>
with TickerProviderStateMixin {
_textClass();
String word;
Timer timer;
@override
void didUpdateWidget(textClass oldWidget) {
if (oldWidget.word != widget.word) {
word = widget.word;
}
super.didUpdateWidget(oldWidget);
}
@override
void initState() {
super.initState();
word = widget.word;
timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) {
setState(() {
word += "t";
});
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
return new Text(word);
}
}
我在使用 Stateful Widgets 时遇到了一些与 setState 函数相关的问题,这些 Stateful Widgets 在定时器的帮助下自我更新。下面的代码显示了 2 个 main 类,它们复制了我是如何发现这个错误的。文本小部件 "Lorem" 应在 10 秒内插入 - 它是 - 但从未显示。我尝试调试数组 "Items" 并且它 确实 在 5 秒后包含 "lorem" 文本小部件,这是应该的。 "build" 函数运行但在 UI.
中没有任何区别class textList extends StatefulWidget {
@override
State<StatefulWidget> createState() =>
new _textListState();
}
class _textListState extends State<textList>
with TickerProviderStateMixin {
List<Widget> items = new List();
Widget lorem = new textClass("Lorem");
Timer timer;
@override
void initState() {
super.initState();
items.add(new textClass("test"));
items.add(new textClass("test"));
timer = new Timer.periodic(new Duration(seconds: 5), (Timer timer) {
setState(() {
items.removeAt(0);
items.add(lorem);
});
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
Iterable<Widget> content = ListTile.divideTiles(
context: context, tiles: items).toList();
return new Column(
children: content,
);
}
}
class textClass extends StatefulWidget {
textClass(this.word);
final String word;
@override
State<StatefulWidget> createState() =>
new _textClass(word);
}
class _textClass extends State<textClass>
with TickerProviderStateMixin {
_textClass(this.word);
String word;
Timer timer;
@override
void initState() {
super.initState();
timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) {
setState(() {
word += "t";
});
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
return new Text(word);
}
}
这不是我发现此错误的方式,但这是复制它的最简单方法。主要思想是:子文本应不断更新自己(在本例中,最后添加 "t"s),5 秒后,应将最后一个文本替换为文本小部件 "Lorem" ,列表中发生了什么,但 UI.
中没有这是错误的地方:
- A
State
不应该有任何构造函数参数。使用widget
属性 获取关联StatefulWidget
. 的最终属性
- Flutter 正在重用您的
_textClass
实例,因为 class 名称和键匹配。这是一个问题,因为您只在initState
中设置了widget.word
,所以您没有获取新的word
配置信息。您可以通过为StatefulWidget
实例提供唯一的键来消除它们的歧义并导致旧的State
被处理来解决这个问题,或者您可以保留旧的State
并实现didUpdateWidget
.后一种方法如下所示。
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new Scaffold(
appBar: new AppBar(title: new Text('Example App')),
body: new textList(),
),
));
}
class textList extends StatefulWidget {
@override
State<StatefulWidget> createState() =>
new _textListState();
}
class _textListState extends State<textList>
with TickerProviderStateMixin {
List<Widget> items = new List();
Widget lorem = new textClass("Lorem");
Timer timer;
@override
void initState() {
super.initState();
items.add(new textClass("test"));
items.add(new textClass("test"));
timer = new Timer.periodic(new Duration(seconds: 5), (Timer timer) {
setState(() {
items.removeAt(0);
items.add(lorem);
});
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
Iterable<Widget> content = ListTile.divideTiles(
context: context, tiles: items).toList();
return new Column(
children: content,
);
}
}
class textClass extends StatefulWidget {
textClass(this.word);
final String word;
@override
State<StatefulWidget> createState() =>
new _textClass();
}
class _textClass extends State<textClass>
with TickerProviderStateMixin {
_textClass();
String word;
Timer timer;
@override
void didUpdateWidget(textClass oldWidget) {
if (oldWidget.word != widget.word) {
word = widget.word;
}
super.didUpdateWidget(oldWidget);
}
@override
void initState() {
super.initState();
word = widget.word;
timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) {
setState(() {
word += "t";
});
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
return new Text(word);
}
}