我应该在结尾还是开头调用super.initState?


10

我对在哪里叫super.initSate()颤振感到困惑?在某些代码示例中,它在开头被调用,而在其他示例中,则被称为结尾。有区别吗?

我试图用谷歌搜索,但是没有找到关于此函数调用位置的任何解释。

哪一个是正确的?

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

要么

void initState() {    
  //DO OTHER STUFF
  super.initState();    
}

Answers:


4

确实对mixins 很重要(也正因为如此对您而言

在Flutter框架中重写生命周期方法时,调用super方法是一个范式State。这就是为什么甚至deactivate具有mustCallSuper注释的原因
另外,有些人mixin希望您在函数的特定位置调用那些生命周期方法的超级方法。

这意味着您应该遵循文档并super.dispose dispose方法末尾进行调用因为框架中的mixins State可能是这种情况。
例如:TickerProviderStateMixin断言底:SingleTickerProviderStateMixin super.dispose

在调用super.dispose()之前,必须先处理所有股票代码。

另一个示例:AutomaticKeepAliveMixininitState和中执行逻辑dispose

结论

启动initStatesuper.initState结束你disposesuper.dispose你想成为的方便和安全侧添加mixins到你State
此外,请遵循其他生命周期方法(在其中覆盖的任何方法)的文档。State)因为框架将期望您按照文档中的说明调用超级方法。

因此,以下是您应该做的:

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

然而,它并不真的不管了State,我将在下文中,甚至混入解释,它只事项断言,从我能找到的判断-所以它不会影响您的生产应用。

没关系 State

我认为Pablo BarreraCopsOnRoad的前两个答案具有误导性,因为事实的真相是,这确实无关紧要,并且您不需要放远视线

那唯一的行动super.initState,并super.dispose采取了State类本身是断言,自assert-statements在只计算调试模式,这非常重要不是在所有曾经编写的程序,即在生产模式。


在下面的内容中,我将指导您完成in super.initStatesuper.dispose工作State,这是在没有其他mixin时将要执行的所有代码。

initState

让我们确切地看一下super.initState首先执行什么代码(源代码):

@protected
@mustCallSuper
void initState() {
  assert(_debugLifecycleState == _StateLifecycle.created);
}

如您所见,只有生命周期断言,其目的是确保小部件正常工作。因此,只要您在自己的super.initState 某个位置调用initState,您就会看到AssertionError窗口小部件是否无法正常工作。无论您是否采取了任何先前的操作都没有关系,因为assert仅仅是要报告代码中的某些内容还是有问题,即使您super.initState在方法的最后调用,您也会看到该错误。

dispose

dispose方法类似于():

@protected
@mustCallSuper
void dispose() {
  assert(_debugLifecycleState == _StateLifecycle.ready);
  assert(() {
    _debugLifecycleState = _StateLifecycle.defunct;
    return true;
  }());
}

如您所见,它还仅包含处理调试生命周期检查的断言。第二个assert是一个不错的技巧,因为它确保_debugLifecycleState仅在调试模式下更改-(因为assert-statement仅在调试模式下执行)。
这意味着只要您在自己的方法中的super.dispose 某处进行调用,就可以在没有mixin添加其他功能的情况下失去任何价值。


1
Flutter的官方文档不是很好:(感谢您的回答:)
CopsOnRoad

感谢您的解释,您还介意解释一下,initState()方法中只有一行是assert(...),那么即使super.initState()在生产应用中调用也有什么好处呢?
CopsOnRoad

1
多谢。现在有道理了!因此,我想为了安全起见,为了良好的编程习惯,最好将其保留在代码的开头。
K Vij

@creativecreatorormaybenot这意味着mustCallSuper自Flutter成立以来,Flutter团队将这种方法投入了2年多的时间了。先生,把它放在那里有什么好处?
CopsOnRoad

@creativecreatorormaybenot即使团队为它创建了它mixin,仍然会有一个单独的声明,initStateassert(...),甚至要求super.initState()生产应用程序有什么意义?
CopsOnRoad

3

super.initState()应该始终是方法的第一行initState

从文档:

initState():如果覆盖此方法,请确保您的方法以对super.initState()的调用开头。


2

正如您在框架的类中所看到的那样,您应该在初始化小部件(即之后)之后执行所有操作super.initState()

在逻辑上,我要以另一种方式处理的情况是,首先执行所有操作,然后调用super.dispose()

@override
void initState() {
  super.initState();
  // DO STUFF
}

@override
void dispose() {
  // DO STUFF
  super.dispose();
}

谢谢。但是我在一些代码示例中注意到了这一点。它在initState方法的结尾被调用...
K Vij

我就是
这么

0

每当将新的有状态窗口小部件添加到窗口小部件树中时,默认情况下都会调用initState。现在,super.initState执行小部件基类的默认实现,如果在super.initState之前调用任何依赖基类的东西,这可能会导致问题。这就是为什么建议您以这种方式调用initState的原因:

@override
void initState() {
  super.initState();
  // DO STUFF
}

推理有点缺陷,因为dispose正相反。该框架希望您super.dispose 在最后调用,但是建议是正确的。
creativecreatoror可能

因为如果在处理其他事物之前调用super.dispose,则取决于您的基类的组件可能会发生冲突。
阿尼鲁德·沙玛
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.