setState不会更新用户界面
问题内容:
我在使用有状态的小部件时遇到了一些与setState函数有关的问题,这些小部件在计时器的帮助下进行了自我更新。
下面的代码显示了2个主要类,它们复制了我如何找到此错误的方法。该文本组件“排版”应该在10秒内插入-这是- ,但它从来没有显示。我试图调试数组“ Items”,并且 在5秒钟后确实包含
“ lorem” Text Widget,这是应该的。“ 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”),并且在5秒钟后,
应将其最后一个替换为文本小部件“ Lorem”,这会发生什么情况在列表中,但不在用户界面中。
问题答案:
这是怎么回事:
- A
State
绝对不能有任何构造函数参数。使用该widget
属性可以访问关联的的最终属性StatefulWidget
。 -
Flutter
正在重用您的_textClass
实例,因为类名和键匹配。这是一个问题,因为您仅进行了设置widget.word
,initState
因此您不会选择新的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
StatecreateState() =>
new _textListState();
}class _textListState extends State
with TickerProviderStateMixin {List
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) {
Iterablecontent = ListTile.divideTiles(
context: context, tiles: items).toList();return new Column( children: content, );
}
}class textClass extends StatefulWidget {
textClass(this.word);final String word;
@override
StatecreateState() =>
new _textClass();
}class _textClass extends State
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);
}
}