了解 Flutter didChangeDependencies 机制

mFe*_*ein 13 flutter

阅读文档后在这里State生命周期在这里,我仍然不知道如何didChangeDependencies工作。

据我所知,它将initState在 a 的任何更改之后和之后触发InheritedWidget,但是这些更改是什么?我认为了解触发什么变化很重要didChangeDependencies,这样我们才能了解何时以及如何正确使用它。

Ben*_*rth 8

总长DR

作为 Widget 的创建者,您InheritedWidget可以使用ofmaybeOf等设置它的依赖项( ),因此您应该了解它们何时调用updateShouldNotify(或者它们的依赖项调用它)。这相当复杂:

用法

您通常不必重写此方法,State因为无论如何,当依赖项发生更改时,您的小部件都会重建。如果您想做昂贵的工作,例如发出网络请求,那么您将避免在正常构建中发出该网络请求,而是将这项昂贵的工作放入其中didChangeDependencies。这允许您仅在依赖项发生更改时才进行这些昂贵的操作。老实说,我很难想象一种情况,如果你正确InheritedWidget地将应用程序的逻辑构建到服务中,如果发生变化,你会纯粹想要进行昂贵的操作。所以我查看了 Flutter 框架的内部结构......

覆盖示例didChangeDependencies

  • Flutter 的Image小部件(评论是我的评论,说实话load可能不是我使用的正确词,但resolve恕我直言,也好不了多少)
  @override
  void didChangeDependencies() {
    _updateInvertColors(); // Checks if the image should inverted or not.
    _resolveImage(); // Reloads the image if necessary?

    if (TickerMode.of(context)) // This method returns a bool: Whether tickers in the given subtree should be enabled or disabled.
      _listenToStream(); // Keep loading the image
    else
      _stopListeningToStream(keepStreamAlive: true); // Be efficient and not read from the stream if not needed. (ticker is false)

    super.didChangeDependencies();
  }
Run Code Online (Sandbox Code Playgroud)
  • 什么时候被didChangeDependencies调用?又名。Image 的依赖项是什么(全部InheritedWidgets)?它使用ofmaybeOf注册InheritedWidget依赖项,包括MediaQuery, Directionality, DefaultAssetBundle, TickerMode, Localizations。因此,当这些依赖项更改/更新时,Image调用。didChangeDependencies

什么是依赖?

您使一个小部件依赖InheritedWidget于with的子类型InheritedWidgetType.of(context),该子类型在内部调用context.dependOnInheritedWidgetOfExactType<InheritedWidgetType>();. 所以小部件对此有依赖性InheritedWidget。例如,Theme.of(BuildContext context)可以在这里看到。

从 Flutter 框架评论中的文档中可以看出dependOnInheritedWidgetOfExactType

获取给定类型的最近的小部件T,该小部件必须是具体的 [InheritedWidget] 子类的类型,并将此构建上下文注册到该小部件,以便当该小部件发生更改(或引入该类型的新小部件,或小部件消失),此构建上下文被重建,以便它可以从该widget获取新值。

一旦小部件通过调用此方法注册了对特定类型的依赖关系,它将被重建,并且只要发生与该小部件相关的更改,就会调用 [State.didChangeDependency] ,直到下一次移动该小部件或其祖先之一(例如,因为添加或删除了祖先)。

还有更多文档,非常有趣,请阅读


目前, Jitesh 的答案是错误的。依赖关系不是 Widget 的状态,它们仅与InheritedWidget.


Gün*_*uer 7

当 Flutter 调用updateShouldNotify()并返回 时true,则build()通过didChangeDependencies调用来通知先前请求继承小部件的小部件。

updateShouldNotifytrue如果它的状态自上次调用以来发生了变化,则应该返回。


jit*_*555 6

didChangeDependencies()当此 [State] 对象的依赖项发生更改时调用。\n那么,它到底是如何调用的?根据上面的定义,看起来它会在状态更改后被调用,但是我们如何知道状态已更改?\n示例:\n下面的示例使用 Provider 状态管理机制从父窗口小部件更新子窗口小部件。Provider 有一个名为 updateShouldNotify 的属性,它决定状态是否更改。如果它返回 true,则仅在 ChildWidget 类中调用 didChangeDependency。\nupdateShouldNotify 在内部默认返回 true,因为它知道状态已更改。

\n

为什么我们需要 updateShouldNotify?

\n

它\xe2\x80\x99s是必需的,因为如果有人想在特定条件下更新状态。例如:如果 UI 需要仅显示偶数值,那么我们可以添加一个条件,例如

\n
updateShouldNotify: (oldValue, newValue) => newValue % 2 == 0,\n
Run Code Online (Sandbox Code Playgroud)\n

代码片段:

\n
class ParentWidget extends StatefulWidget {\n  ParentWidget({Key key, this.title}) : super(key: key);\n  final String title;\n  @override\n  _ParentWidgetState createState() => _ParentWidgetState();\n}\nclass _ParentWidgetState extends State<ParentWidget> {\n  int _counter = 0;\n  void _incrementCounter() {\n    setState(() {\n      _counter++;\n    });\n  }\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(\'Life Cycle\'),\n      ),\n      body: Provider.value(\n        value: _counter,\n        updateShouldNotify: (oldValue, newValue) => true,\n        child: Center(\n          child: Column(\n            mainAxisAlignment: MainAxisAlignment.center,\n            children: <Widget>[\n              Text(\n                \'Press Fab button to increase counter:\',\n              ),\n              ChildWidget()\n            ],\n          ),\n        ),\n      ),\n      floatingActionButton: FloatingActionButton(\n        onPressed: _incrementCounter,\n        tooltip: \'Increment\',\n        child: Icon(Icons.add),\n      ),\n    );\n  }\n}\nclass ChildWidget extends StatefulWidget {\n  @override\n  _ChildWidgetState createState() => _ChildWidgetState();\n}\nclass _ChildWidgetState extends State<ChildWidget> {\n  int _counter = 0;\n  @override\n  void initState() {\n    print(\'initState(), counter = $_counter\');\n    super.initState();\n  }\n  @override\n  void didChangeDependencies() {\n    _counter = Provider.of<int>(context);\n    print(\'didChangeDependencies(), counter = $_counter\');\n    super.didChangeDependencies();\n  }\n  @override\n  Widget build(BuildContext context) {\n    print(\'build(), counter = $_counter\');\n    return Text(\n      \'$_counter\',\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

输出日志:

\n
I/flutter ( 3779): didChangeDependencies(), counter = 1\nI/flutter ( 3779): build(), counter = 1\n
Run Code Online (Sandbox Code Playgroud)\n

欲了解更多信息:

\n

https://medium.com/@jitsm555/ Differentiate- Between-didchangedependency-and-initstate-f98a8ae43164

\n

  • 对我来说,混淆的主要根源是“依赖”的模糊概念。我在文档中找不到依赖项的正式定义。唯一的提示是这句话:_如果之前的构建调用引用了后来更改的 InheritedWidget_。在这方面,我发现这个例子令人困惑:“_ChildWidgetState”的“build”方法没有“引用”任何底层的“InheritedWidget”,不是吗?那么,如果对提供者的唯一“引用”来自“didChangeDependency”本身,那么 Flutter 如何知道提供者是一个依赖项呢? (3认同)