在父setState之后,将子状态对象替换为(initState)而不是update(didUpdateWidget)

时间:2019-07-10 20:32:45

标签: flutter dart

我有一个父母和一个孩子有状态的小部件。通常,当父级重建时,我希望它可以重用现有的子级状态并调用didUpdateWidget。

但是,就我而言,它没有这样做;相反,它将创建一个全新的状态对象并对其调用initState,从而丢失我之前的所有状态信息。

医生说

By default, the framework matches widgets in the current and previous build according 
to their runtimeType and the order in which they appear.

首先,在这种情况下,“顺序”是什么意思?我假设这意味着在小部件树中的位置,对不对? 其次,由于我的窗口小部件树没有更改,因此我希望Flutter重用旧状态而不创建新状态。 我不确定如何调试它。如何检查新旧小部件的“顺序”以查看它们是否不同?

我的代码库相当大,因此我将尝试仅包括相关部分:

class Parent extends StatefulWidget {
  @override
  _ParentState createState() => _ParentState();
}

class _ParentState extends State<Parent> {
  String _remaining;

  void updateRemaining(String remaining) {
    setState(() => _remaining = remaining);
  }

  Widget build(BuildContext context) {
    //somewhere
    return Child(updateRemaining:updateRemaining);
  }
}

class Child extends StatefulWidget {
  final Function updateRemaining;
  Child({this.updateRemaining});

  @override
  _ChildState createState() => new _ChildState();
}

class _ChildState extends State<Child> {

//somewhere:
widget.updateRemaining("0");
}

在最后一次调用之后:widget.updateRemaining(“ 0”);颤动处理子状态并创建一个新状态,而不是重用旧状态。

我用Flutter检查器查看了小部件树,然后,它看起来像Homepage(= child小部件)相对于MainApp(= parent小部件)没动

widget.updateRemaining(“ 0”);之前;致电 before widget.updateRemaining("0"); call

在widget.updateRemaining(“ 0”);之后;致电 after widget.updateRemaining("0"); call

1 个答案:

答案 0 :(得分:0)

好,这是我 Think 发生的事情-如果我错了,请纠正我。 答案在我附加的小部件树中。 如您所见,Scaffold具有一个GlobalKey,它会更改并因此强制进行重建,因为根据doc:

  

使用键控制框架与其他窗口小部件匹配的窗口小部件   小部件重建时的小部件。默认情况下,框架匹配   当前和先前构建中的窗口小部件   runtimeType及其出现的顺序。 使用键,   框架要求两个小部件具有相同的键,以及   相同的runtimeType。

由于键不同,因此将脚手架状态对象(包括其所有子控件)放置并创建一个新的。 显然,创建一个新的状态对象也将强制重新创建整个子树,而不管其是否与旧的子树相同。