我是flutter的新手,当我想在InitState中调用我的上下文时,它会抛出一个错误:它是关于BuildContext.inheritFromWidgetOfExactType
的,但是我使用了didChangeDependencies,它可以正常工作。
现在我有两个问题:
1-为什么在initState中调用我们的上下文不起作用,但在从didChangeDependencies中调用时却起作用?(因为我在官方文档This method is also called immediately after [initState]
中读到,这两个都将在构建方法之前被调用。
2-为什么我们可以访问构建方法之外的上下文(因为在那里我们有build(BuildContext context)
,我们可以使用我们的上下文,但在didChangeDependencies中,我们没有像didChangeDependencies(BuildContext context)
这样的东西,所以我们可以从哪里调用上下文来使用它)?
9条答案
按热度按时间tyky79it1#
从State加载其依赖项的那一刻起,我们就可以使用State的上下文。
在调用build时,
context
是可用的,并作为参数传递。现在继续,
initstate
在状态加载其依赖项之前被调用,因此没有可用的上下文,如果在 initstate 中使用上下文,则会得到一个错误。然而,didChangeDependencies
在状态加载其依赖项后不久被调用,此时上下文可用,因此您可以在这里使用上下文。然而,它们都是在调用
build
之前调用的。唯一的区别是,一个是在状态加载其依赖项之前调用的,另一个是在状态加载其依赖项之后不久调用的。2uluyalo2#
我发现
initState
和didChangeDependencies
之间有一个显著的区别:initState
对于一个widget只调用一次。didChangeDependencies
可能在每个小部件生命周期中被调用多次(在我的例子中,它是在键盘出现/消失时被调用的)csga3l583#
initState()
当新的Widget插入到树中时调用。框架将为它创建的每个[State]对象调用此方法一次。这将被调用一次,因此执行只需要执行一次的工作,但记住context
不能在这里使用,因为widget状态被加载,只有initState()
工作被完成。语法:
didChangeDependencies()
当这个[State]对象的依赖关系改变时调用。那么,确切地说,**它是如何被调用的?**根据上面的定义,它看起来像是在状态改变后被调用的,但是我们如何知道状态被改变了呢?
示例:
下面的示例使用
Provider
状态管理机制来更新父控件的子控件。Provider
有一个名为updateShouldNotify
的属性,该属性决定状态是否更改。如果它返回true
,则只有didChangeDependencies
在ChildWidget
类中被调用。updateShouldNotify在内部默认返回true,因为它知道状态发生了变化。**那么为什么我们需要updateShouldNotify?**它的需要是因为如果有人想要在特定条件下更新状态,例如:如果UI只需要显示
even
值,那么我们可以添加一个条件,如代码段:
输出日志:
详细说明:
https://medium.com/@jitsm555/differentiate-between-didchangedependencies-and-initstate-f98a8ae43164?sk=47b8dda310f307865d8d3873966a9f4f
fhg3lkii4#
initState
documentation不能从此方法中使用
BuildContext.inheritFromWidgetOfExactType
。但是,将在此方法之后立即调用didChangeDependencies
,并且可以在此方法中使用BuildContext.inheritFromWidgetOfExactType
。所以你需要在
didChangeDependencies
中使用BuildContext.inheritFromWidgetOfExactType
。1.每个Widget都有自己的
context
。这就是为什么你可以访问构建方法之外的上下文。关于
build(BuildContext context)
,build
方法从父控件接受context
。这意味着这个参数BuildContext context
不是当前控件的上下文,而是其父控件的上下文。w46czmvw5#
context
在build()
之外神秘地可访问的概念是困扰我的一个。我认为澄清这个微妙的点补充了对第一个问题的其他答案中给出的解释。如何从
build()
方法外部访问context
?混乱源于(错误)假设
context
需要传递给State.build()
。请注意,State
类已经有一个context
属性,根据文档,它在这里被“冗余地提供”给build()
,以便它的签名与WidgetBuilder
的签名匹配。但是,这不是与StatelessWidget
相同的build()
方法。v64noz0r6#
initState()
是小部件创建后调用的第一个方法,类似于Android中的onCreate()
或iOS中的viewDidLoad()
。框架第一次构建小部件时,它会在
initState()
之后调用didChangeDependencies()
,如果状态对象依赖于一个已更改的继承小部件,它可能会再次调用didChangeDependencies()
。来源:Flutter Apprentice由Kodeco出版
9vw9lbht7#
当此State对象的依赖项更改时调用。
例如,如果先前对build的调用引用了一个后来更改的InheritedWidget,则框架将调用此方法来通知此对象有关更改。
该方法也是在initState之后立即调用的,从该方法调用BuildContext.dependOnInheritedWidgetOfExactType是安全的。
事实上,子类很少覆盖这个方法,因为框架总是在依赖关系改变后调用build。一些子类确实覆盖这个方法,因为当它们的依赖关系改变时,它们需要做一些昂贵的工作(例如,网络获取),并且这些工作对于每个构建来说都太昂贵了。
6qqygrtg8#
StatefulWidget
的State
类具有context
属性。此生成上下文首先在didChangeDependencies
中可用。尝试在initState
中使用context
将导致错误。按以下顺序运行print语句:
参见Working with didChangeDependencies() in Flutter
x6492ojm9#
你仍然可以在initState()方法中使用context,它的hack但是工作,所有你需要做的就是寻找延迟,无论你需要执行什么,都有上下文,就像这样: