dart 如何将回调传递给另一个StatefulWidget?

zc0qhyus  于 2023-03-21  发布在  其他
关注(0)|答案(4)|浏览(123)

例如,我有两个StatefulWidget来监视同一个回调方法,我应该怎么做?如果我有三个以上的StatefulWidget来监视它的事件呢?

class WidgetOne extends StatefulWidget {
  @override
  _WidgetOneState createState() => new _WidgetOneState();
}

class _WidgetOneState extends State<WidgetOne> {

  // this is the callback, the widget two want listen the callback too
  bool _onNotification(ScrollNotification notification){

  }

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: <Widget>[
        new NotificationListener(child: new ListView(shrinkWrap: true,),
          onNotification: _onNotification),
        new WidgetTwo()
      ],
    );
  }
}

class WidgetTwo extends StatefulWidget {
  @override
  _WidgetTwoState createState() => new _WidgetTwoState();
}

class _WidgetTwoState extends State<WidgetTwo> {

  // in this,How Can I get the callback in WidgetOne?
  @override
  Widget build(BuildContext context) {
    return new Container();
  }
}
0lvr5msh

0lvr5msh1#

你不能也不应该这样做,小部件永远不应该依赖于其他小部件的架构。
您有两种可能性:

  • 合并WidgetTwoWidgetOne。因为将它们分开没有意义(至少对于您提供的内容来说)。
  • 修改WidgetTwo以获取一个子元素,并将该ListView添加为WidgetTwo的子元素,以便它可以将列表 Package 到自己的NotificationListener中。
e5nszbig

e5nszbig2#

您的解决方案可以通过使用setState()并在WidgetTwo的构造函数中传递状态函数来实现。我在下面做了一个示例,这个示例的主要思想是我将MyHomePage作为我的主控件,并将MyFloatButton作为主控件。(我想将其定制为另一个StatefulWidget),所以当按下FAB时,我需要调用MyHomePage中的递增计数器函数。让我们看看下面我是如何做到的。

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  //Consider this function as your's _onNotification and important to note I am using setState() within :)
  void _incrementCounter() { 
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(
          widget.title,
          style: TextStyle(color: Colors.white),
        ),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              'You have pushed the button $_counter times:',
              style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
      floatingActionButton: new MyFloatButton(_incrementCounter),//here I am calling MyFloatButton Constructor passing _incrementCounter as a function
    );
  }
}

class MyFloatButton extends StatefulWidget {

  final Function onPressedFunction;

  // Here I am receiving the function in constructor as params
  MyFloatButton(this.onPressedFunction);

  @override
  _MyFloatButtonState createState() => new _MyFloatButtonState();
}

class _MyFloatButtonState extends State<MyFloatButton> {
  @override
  Widget build(BuildContext context) {
    return new Container(
      padding: EdgeInsets.all(5.0),
      decoration: new BoxDecoration(color: Colors.orangeAccent, borderRadius: new BorderRadius.circular(50.0)),
      child: new IconButton(
        icon: new Icon(Icons.add),
        color: Colors.white,
        onPressed: widget.onPressedFunction,// here i set the onPressed property with widget.onPressedFunction. Remember that you should use "widget." in order to access onPressedFunction here!
      ),
    );
  }
}

现在把我的主页当作小部件一,把我的浮动按钮当作小部件二,把_incrementCounter函数当作你的_onNotification,希望你能达到你想要的效果:)
(我做了一般性的例子,这样任何人都可以根据他们所面临的场景理解)

v8wbuo2f

v8wbuo2f3#

您可以为有状态小部件使用内置的widget属性。
https://api.flutter.dev/flutter/widgets/State/widget.html
因此在WidgetOne中它将是

new WidgetTwo(callback: callback)

WidgetTwo

class WidgetTwo extends StatefulWidget {
  final Function callback;
  
  WidgetTwo({this.callback});

  @override
  _WidgetTwoState createState() => new _WidgetTwoState();
}

_WidgetTwoState中,您可以将其作为

widget.callback
wi3ka0sx

wi3ka0sx4#

另一种方法是在子组件内部定义一个回调接口,用它来通知父组件,例如class OutagesScreen extends StatefulWidget是父组件,class PrefecturesDropdown extends StatefulWidget是子组件。
在子组件内部定义回调接口,即:

typedef PrefectureDtoCallback = PrefectureDto Function(PrefectureDto);

在子组件的构造函数上,定义预期的回调,如下所示:

/// Callback to return the selected prefecture to the parent component.
  final PrefectureDtoCallback currentPrefectureCallback;
  const PrefecturesDropdown(this.currentPrefectureCallback, {Key? key})
      : super(key: key);

现在,在子组件上执行操作时,您可以通过定义的回调通知父组件。在本例中,我们通知新选择的县:

onChanged: (PrefectureDto? newValue) {
        setState(() {
          defaultPrefecture = newValue!;
          widget.currentPrefectureCallback(
              newValue); // Notify about the new selected prefecture.
        });
      }

现在,在父组件上,您可以接收如下通知:

return FutureBuilder(
      future: _getOutages(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Scaffold(
            body: Column(children: [
              PrefecturesDropdown((value) {
                // Receive the notification
                return selectedPrefecture = value;
              }),
              Flexible(
                child: outagesList(context),
              )
            ]),
          );
        }

你可以在GitHub: Black Out上找到一个完整的工作示例。这里讨论的实现的特定文件是outages.dart(父组件)和prefectures_dropdown.dart(子组件)。

相关问题