在initState

时间:2019-07-23 15:18:20

标签: flutter dart state inherited-widget

我需要一些帮助来了解如何从继承的小部件中获取数据。

我通常使用

直接从build方法的小部件中获取参数
  @override
  Widget build(BuildContext context) {    
   //THIS METHOD
   var data = StateContainer.of(context).data;

   return Container(child:Text("${data.parameter}"));
  }

但是由于还没有buildContext,所以不能从initState调用此方法。

我需要在initState方法中具有该参数(我在那从服务器中调用我的数据,并且需要将该数据传递给我的函数),那么,我该怎么做呢?

@override
void initState() {
 otherData = fetchData(data);
 super.initState();
}

我尝试使用didChangeDipendencies(),但每次重建视图时都会调用它(从屏幕弹出等),因此它不是我要使用的,也不是FutureBuilder小部件。

有什么建议吗?

4 个答案:

答案 0 :(得分:1)

首先,请注意,您可能要做要使用didChangeDependencies。但是您不能不做任何检查就直接在那打来电话。您需要先将其包装在if中。

典型的didChangeDependencies实现应类似于:

Foo foo;

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  final foo = Foo.of(context);
  if (this.foo != foo) {
    this.foo = foo;
    foo.doSomething();
  }
}

使用此类代码,doSomething更改后,将仅执行 foo


或者,如果您很懒惰并且确定您的对象永远不会改变,那么还有另一种解决方案。

要获取InheritedWidget,通常使用的方法是:

BuildContext context;
InheritedWidget foo = context.inheritFromWidgetOfExactType(Foo);

并且不能在initState内部调用此方法。

但是还有另一种方法可以做同样的事情:

BuildContext context;
InheritedWidget foo = context.ancestorInheritedElementForWidgetOfExactType(Foo)?.widget;

转折点是: -可以在initState内部调用此方法 -无法处理更改值的情况。

因此,如果您的价值从未改变,则可以使用它。

答案 1 :(得分:0)

1,如果仅需要 InheritedWidget 作为 Widget 的参数提供者。 您可以像下面这样在 initState 上使用

@override
void initState() {
    super.initState();
    var data = context.ancestorInheritedElementForWidgetOfExactType(type)?.widget;
}

2,如果 InheritedWidget 的数据发生更改时,如果需要侦听器以重新呈现窗口小部件,则为

。建议您在 StatelessWidget 内包装 StatefulWidget ,   StatefulWidget 的参数是从 StatelessWidget 传递的,当 InheritedWidget 更改数据时,它将在上通知 StatelessWidget > StatefulWidget ,我们将在 didChangeDependencies 上进行更改,您可以刷新数据。 这是代码指南:

class WrapperDemoWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    DemoData data = StateContainer.of(context).data;
    return Container();
  }
}

class ImplementWidget extends StatefulWidget {

  DemoData data;

  ImplementWidget({this.data});

  @override
  _ImplementWidgetState createState() => _ImplementWidgetState();
}

class _ImplementWidgetState extends State<ImplementWidget> {

  @override
  void initState() {
    super.initState();
   //TODO Do sth with widget.data
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //TODO Do change with widget.data
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

答案 2 :(得分:-1)

我更喜欢使用didChangeDependencies的解决方案,因为Future.delayed的解决方案有点破绽,看起来不专业且不健康。但是,它开箱即用。

这是我更喜欢的解决方案:

class _MyAppState extends State<MyApp> {

    bool isDataLoaded = false;

    @override
  void didChangeDependencies() {
    if (!isDataLoaded) {
            otherData = fetchData(data).then((_){
                this.isDataLoaded = true;
            });
    }
    super.didChangeDependencies();
  }
...

答案 3 :(得分:-2)

您还可以在initState中获取上下文,尝试使用持续时间为零的Future。您可以找到一些示例here

void initState() {
    super.initState();
      Future.delayed(Duration.zero,() {
        //use context here
      showDialog(context: context, builder: (context) => AlertDialog(
          content: Column(
            children: <Widget>[
              Text('@todo')
            ],
          ),
          actions: <Widget>[
            FlatButton(onPressed: (){
              Navigator.pop(context);
            }, child: Text('OK')),
          ],
        ));
      });
  }

我用它来使用继承的窗口小部件来加载屏幕,并避免一些全局变量