Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter didChangeDependencies和initState之间有什么区别?_Flutter_Dart - Fatal编程技术网

Flutter didChangeDependencies和initState之间有什么区别?

Flutter didChangeDependencies和initState之间有什么区别?,flutter,dart,Flutter,Dart,我不熟悉flifter,当我想在InitState中调用我的上下文时,它会抛出一个错误: 关于 BuildContext.inheritFromWidgetOfExactType 但是我使用了didChangeDependencies,它工作正常 现在我有两个问题: 1-为什么在initState中调用我们的上下文不起作用,但在从didChangeDependencies调用时却起作用? (因为正如我在官方文档中读到的那样,这个方法也会在[initState]之后立即调用, 这两个函数都将在生成

我不熟悉flifter,当我想在InitState中调用我的上下文时,它会抛出一个错误: 关于
BuildContext.inheritFromWidgetOfExactType
但是我使用了didChangeDependencies,它工作正常

现在我有两个问题:

1-为什么在initState中调用我们的上下文不起作用,但在从didChangeDependencies调用时却起作用? (因为正如我在官方文档
中读到的那样,这个方法也会在[initState]
之后立即调用, 这两个函数都将在生成方法之前调用。)

2-为什么我们可以访问构建方法之外的上下文(因为在那里我们有
build(BuildContext)
,我们可以使用上下文,但在didChangeDependencies中我们没有类似于
didChangeDependencies(BuildContext)
,所以我们可以从哪里调用上下文来使用它)

  • 无法从此方法中使用
    BuildContext.inheritFromWidgetOfExactType
    。但是,此方法之后将立即调用
    didChangeDependencies
    ,并且可以在那里使用
    BuildContext.inheritFromWidgetOfExactType

    因此,您需要在
    didChangeDependencies
    中使用
    BuildContext.inheritFromWidgetOfExactType

  • 每个小部件都有自己的
    上下文。这就是为什么您可以访问构建方法外部的上下文
    关于
    build(BuildContext)
    build
    方法从父窗口小部件接受
    context
    。这意味着此参数
    BuildContext
    不是当前小部件的上下文,而是其父部件的上下文。

    答案是

    不应从小部件构造函数或State.initState方法调用此方法,因为如果继承的值发生更改,则不会再次调用这些方法。若要确保小部件在继承的值更改时正确更新自身,请仅从构建方法、布局和绘制回调或State.didChangeDependencies调用它(直接或间接)

    从状态加载其依赖项的那一刻起,状态的上下文就对我们可用

    在调用build时,上下文对我们可用,并作为参数传递

    现在继续, initstate在状态加载其依赖项之前被调用,因此没有上下文可用,如果在initstate中使用上下文,则会出现错误。 然而,didChangeDependencies仅在状态加载其依赖项后几分钟被调用,此时上下文可用,因此您可以在这里使用上下文

    但是,在调用build之前会调用这两个函数。 唯一的区别是,一个在状态加载其依赖项之前调用,另一个在状态加载其依赖项之后几分钟调用


    我发现
    initState
    didChangeDependencies
    之间存在显著差异:

    • initState
      对于小部件只调用一次
    • didChangeDependencies
      可以在每个小部件生命周期中调用多次(在我的例子中,它是在键盘出现/消失时调用的)

    当此状态对象的依赖项更改时调用

    例如,如果上一次对构建的调用引用了一个后来更改的继承的widget,则框架将调用此方法来通知此对象该更改

    此方法也会在initState之后立即调用。可以安全地从此方法调用BuildContext.dependonheritedWidgeToFexactType

    事实上,子类很少重写此方法,因为框架总是在依赖项更改后调用build。有些子类确实会重写此方法,因为当它们的依赖项发生变化时,它们需要执行一些昂贵的工作(例如,网络获取),而这些工作对于每个构建来说都太昂贵了。

    initState()
    在树中插入新小部件时调用。 框架将为每个[State]对象调用此方法一次 它创造了。这将被调用一次,因此执行只需要执行一次的工作,但请记住这里不能使用
    上下文
    ,因为小部件状态仅加载
    initState()
    工作已完成

    语法:

    @override
      void initState() {
        debugPrint('initState()');
        super.initState();
      }
    
    class ParentWidget extends StatefulWidget {
      ParentWidget({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _ParentWidgetState createState() => _ParentWidgetState();
    }
    
    class _ParentWidgetState extends State<ParentWidget> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Life Cycle'),
          ),
          body: Provider.value(
            value: _counter,
            updateShouldNotify: (oldValue, newValue) => true,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'Press Fab button to increase counter:',
                  ),
                  ChildWidget()
                ],
              ),
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    }
    
    class ChildWidget extends StatefulWidget {
      @override
      _ChildWidgetState createState() => _ChildWidgetState();
    }
    
    class _ChildWidgetState extends State<ChildWidget> {
      int _counter = 0;
    
      @override
      void initState() {
        print('initState(), counter = $_counter');
        super.initState();
      }
    
      @override
      void didChangeDependencies() {
        _counter = Provider.of<int>(context);
        print('didChangeDependencies(), counter = $_counter');
        super.didChangeDependencies();
      }
    
      @override
      Widget build(BuildContext context) {
        print('build(), counter = $_counter');
        return Text(
          '$_counter',
        );
      }
    }
    
    I/flutter ( 3779): didChangeDependencies(), counter = 1
    I/flutter ( 3779): build(), counter = 1
    
    didChangeDependencies()
    当此[State]对象的依赖项更改时调用

    所以,确切地说,它是如何被调用的?根据上面的定义,它看起来像是在状态改变后被调用的,但是我们如何知道状态改变了呢

    示例:

    @override
      void initState() {
        debugPrint('initState()');
        super.initState();
      }
    
    class ParentWidget extends StatefulWidget {
      ParentWidget({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _ParentWidgetState createState() => _ParentWidgetState();
    }
    
    class _ParentWidgetState extends State<ParentWidget> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Life Cycle'),
          ),
          body: Provider.value(
            value: _counter,
            updateShouldNotify: (oldValue, newValue) => true,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'Press Fab button to increase counter:',
                  ),
                  ChildWidget()
                ],
              ),
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    }
    
    class ChildWidget extends StatefulWidget {
      @override
      _ChildWidgetState createState() => _ChildWidgetState();
    }
    
    class _ChildWidgetState extends State<ChildWidget> {
      int _counter = 0;
    
      @override
      void initState() {
        print('initState(), counter = $_counter');
        super.initState();
      }
    
      @override
      void didChangeDependencies() {
        _counter = Provider.of<int>(context);
        print('didChangeDependencies(), counter = $_counter');
        super.didChangeDependencies();
      }
    
      @override
      Widget build(BuildContext context) {
        print('build(), counter = $_counter');
        return Text(
          '$_counter',
        );
      }
    }
    
    I/flutter ( 3779): didChangeDependencies(), counter = 1
    I/flutter ( 3779): build(), counter = 1
    
    下面的示例使用
    提供者
    状态管理机制从父窗口小部件更新子窗口小部件。
    Provider
    有一个名为
    updateShouldNotify
    的属性,它决定是否更改状态。如果它返回
    true
    ,则在
    ChildWidget
    类中只调用
    didChangeDependencies

    updateShouldNotify在内部默认情况下返回true,因为它知道状态已更改那么为什么我们需要更新houldnotify?这是必要的,因为如果有人想在特定条件下更新状态, 例如:如果UI要求只显示
    偶数
    值,那么我们可以添加如下条件

    updateShouldNotify: (oldValue, newValue) => newValue % 2 == 0,
    
    代码片段:

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

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

    您仍然可以在initState()方法中使用context,它的hack-buts可以工作,您所需要做的就是延迟您需要执行的任何包含context的操作,如下所示:

     @override
      void initState() {
        Future.delayed(Duration.zero).then((_) {
          // you code with context here
        });
        super.initState();
      }
    
    这是一个补充答案,显示了OP所描述的内容

    StatefulWidget
    State
    类具有
    context
    属性。此生成上下文首先在
    didChangeDependencies
    中可用。试图