【问题标题】:How to call a function in a Stateful Widget from another StatefulWidget?如何从另一个 StatefulWidget 调用 Stateful Widget 中的函数?
【发布时间】:2021-02-20 18:05:29
【问题描述】:

您好,我想调用 formCliente 类的 StatefulWidget 内的函数来清理控制器。但我想通过 formFinanceiro 类的 StatefulWidget 内的按钮访问它。请帮帮我!谢谢。

      class _CadastrarClienteState extends State<CadastrarCliente>
with TickerProviderStateMixin {     
    body: Form(
      key: formkey,
      child: TabBarView(
        physics: physics, //NeverScrollableScrollPhysics()
        controller: _tabController,
        children: [
          FormCliente(),
          FormDocumento(),
          FormVeiculo(),
          FormContrato(),
          FutureBuilder(
              future: getTrabalhaComCota(),
              builder: (context, snapshot) {
                if (snapshot.hasData && !snapshot.hasError) {
                  //   print(' chamada cota:${snapshot.data}');
                  return FormFinanceiro(
                      itemsCota: snapshot.data, formKey: formkey);
                } else {
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                }
              }),
        ],
      ),
    ),

} ]

【问题讨论】:

    标签: function flutter call stateful


    【解决方案1】:

    您可以使用 Streams 来实现相同的目标,请参阅下面的代码:

    import 'package:flutter/material.dart';
    import 'dart:async';
    
    final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
          debugShowCheckedModeBanner: false,
          home: Scaffold(
            appBar: AppBar(title: Text("Demo")),
            body: MyApps(),
          ),
        );
      }
    }
    
    class MyApps extends StatefulWidget {
      @override
      _MyAppsState createState() => _MyAppsState();
    }
    
    class _MyAppsState extends State<MyApps> {
      final changeNotifier = new StreamController.broadcast();
    
      @override
      void dispose() {
        changeNotifier.close();
        super.dispose();
      }
    
      buttonClicked() => changeNotifier.sink.add(null);
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            FormCliente(
              shouldTriggerChange: changeNotifier.stream,
            ),
            FormFinanceiro(buttonClicked: buttonClicked),
          ],
        );
      }
    }
    
    class FormCliente extends StatefulWidget {
      final Stream shouldTriggerChange;
    
      FormCliente({this.shouldTriggerChange});
    
      @override
      _FormClienteState createState() => _FormClienteState();
    }
    
    class _FormClienteState extends State<FormCliente> {
      StreamSubscription streamSubscription;
    
      @override
      initState() {
        super.initState();
        if (widget.shouldTriggerChange != null) {
          streamSubscription =
              widget.shouldTriggerChange.listen((_) => clearYourFormMethod());
        }
      }
    
      @override
      didUpdateWidget(FormCliente old) {
        super.didUpdateWidget(old);
        if (widget.shouldTriggerChange != old.shouldTriggerChange) {
          streamSubscription.cancel();
          streamSubscription =
              widget.shouldTriggerChange.listen((_) => clearYourFormMethod());
        }
      }
    
      @override
      dispose() {
        super.dispose();
        streamSubscription.cancel();
      }
    
      void clearYourFormMethod() {
        print('Please clear your form here');
      }
    
      @override
      Widget build(BuildContext context) {
        return Text("FormCliente");
      }
    }
    
    class FormFinanceiro extends StatefulWidget {
      final Function buttonClicked;
    
      FormFinanceiro({this.buttonClicked});
    
      @override
      _FormFinanceiroState createState() => _FormFinanceiroState();
    }
    
    class _FormFinanceiroState extends State<FormFinanceiro> {
      @override
      Widget build(BuildContext context) {
        return Column(
          children: <Widget>[
            RaisedButton(
              child: new Text("FormFinanceiro"),
              onPressed: widget.buttonClicked,
            )
          ],
        );
      }
    }
    

    【讨论】:

    • 您可以在此处直接从 dartpad 运行代码 - dartpad.dev/c629242d7eb485809a87495629f8febf 当您单击 FormFinanceiro 时,请在控制台中查看应显示“请在此处清除您的表单”的输出。本质上,您通过单击 FormFinanceiro 中的 Raised 按钮在 FormCliente 中调用 clearYourFormMethod()。
    • 我可以对花药类使用相同的方法吗?
    • 是的,你可以对另一个类使用相同的方法
    • Bluenile 我不明白你为什么使用这个代码? didUpdateWidget(FormCliente old) { super.didUpdateWidget(old); if (widget.shouldTriggerChange != old.shouldTriggerChange) { streamSubscription.cancel(); streamSubscription = widget.shouldTriggerChange.listen((_) => clearYourFormMethod()); } }
    • 为此您需要了解小部件的生命周期。请参考api.flutter.dev/flutter/widgets/State/didUpdateWidget.html。如果 State 的 build 方法依赖于一个自身可以改变状态的对象,例如 ChangeNotifier 或 Stream,或者其他可以订阅接收通知的对象,那么请确保在 initState、didUpdateWidget 和 dispose 中正确订阅和取消订阅:
    【解决方案2】:

    您需要将state 抬起:

    1. _CadastrarClienteState 类中创建控制器。
    2. _CadastrarClienteState 中创建回调
    3. 将控制器传递给孩子FormFinanceiro
    4. 将回调传递给子FormCliente
    5. 现在,修改 FormCliente 中的 onbuttonpressed 函数,以便在按下按钮时调用回调。
    6. 最后在_CadastrarClienteState 中的回调方法中,使用控制器清除值。

    【讨论】:

    • 非常感谢乔伊特伦斯!但是,pass的字段很多,t会很复杂
    猜你喜欢
    • 1970-01-01
    • 2023-01-24
    • 2021-06-08
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-08
    • 2019-02-17
    • 1970-01-01
    相关资源
    最近更新 更多