Trigger a function from a widget to a State object

前端 未结 3 1608
情深已故
情深已故 2020-12-05 12:33

This is a simplified version of the scenario:

class ParentWdiegt extends StatelessWidget{
//
//
floatinActionButton: FloatingActionButtonWidget(onPressed:()=         


        
相关标签:
3条回答
  • 2020-12-05 12:42

    Try to store the state of the widget and then access

    class MySFWidget extends StatefulWidget {
      SFWidgetState currState;
    
      @override
      SFWidgetState createState(){
        currState = new SFWidgetState();
        return currState;
      };
    
    }
    
    class SFWidgetState extends State<MySFWidget> {
    
      int prop;
    
      void SomeMethod(){
        // DO Something
      }
    
      @override
      Widget build(BuildContext context) {
        return null;
      }
    
    }
    

    Then, access its property or call method by :

    myWidgetInstance.currState.prop

    myWidgetInstance.currState.SomeMethod()

    0 讨论(0)
  • 2020-12-05 12:54

    You can use GlobalKey for that:

    // some global place
    final customWidgetKey = new GlobalKey<CustomWidgetState>();
    

    ...

      // import the file with "customWidgetKey"
    
      new CustomWidget(key: customWidetKey, ...)
    

    ...

      // import the file with "customWidgetKey"
    
      floatinActionButton: FloatingActionButtonWidget(
          onPressed: ()=>customWidgetKey.currentState.someMethod(someValue))
    
    0 讨论(0)
  • 2020-12-05 12:58

    While GlobalKey allows for an easy access to any widget's state ; avoid it. Widgets should not interact with other widgets directly. This is one of the core principle of Flutter.

    Flutter uses reactive programming instead. Where widgets communicate with each others by submitting events. Not by directly editing the desired widget.

    The obvious benefit is that widgets stays independant. And potentially dozens of widgets can communicate with each others using the same principle.

    I already made an example here on how to make two different widgets share a common editable value.

    If you want to call methods instead, this uses the same principle : A Listenable or Stream shared between widgets. But without using AnimatedWidget or StreamBuilder for the listening. Instead we'll do the listening manually (which requires slighly more boilerplate) to trigger a custom function.

    Here's an example using Stream.

    import 'dart:async';
    import 'package:flutter/material.dart';
    
    class ParentWidget extends StatefulWidget {
      @override
      _ParentWidgetState createState() => _ParentWidgetState();
    }
    
    class _ParentWidgetState extends State<ParentWidget> {
      final changeNotifier = new StreamController.broadcast();
    
      @override
      void dispose() {
        changeNotifier.close();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return new Column(
          children: <Widget>[
            new AnotherWidget(
              shouldTriggerChange: changeNotifier.stream,
            ),
            new RaisedButton(
              child: new Text("data"),
              onPressed: () => changeNotifier.sink.add(null),
            )
          ],
        );
      }
    }
    
    class AnotherWidget extends StatefulWidget {
      final Stream shouldTriggerChange;
    
      AnotherWidget({@required this.shouldTriggerChange});
    
      @override
      _AnotherWidgetState createState() => _AnotherWidgetState();
    }
    
    class _AnotherWidgetState extends State<AnotherWidget> {
      StreamSubscription streamSubscription;
    
      @override
      initState() {
        super.initState();
        streamSubscription = widget.shouldTriggerChange.listen((_) => someMethod());
      }
    
      @override
      didUpdateWidget(AnotherWidget old) {
        super.didUpdateWidget(old);
        // in case the stream instance changed, subscribe to the new one
        if (widget.shouldTriggerChange != old.shouldTriggerChange) {
          streamSubscription.cancel();
          streamSubscription = widget.shouldTriggerChange.listen((_) => someMethod());
        }
      }
    
      @override
      dispose() {
        super.dispose();
        streamSubscription.cancel();
      }
    
      void someMethod() {
        print('Hello World');
      }
    
      @override
      Widget build(BuildContext context) {
        return Container();
      }
    }
    

    In this example, someMethod of AnotherWidget will be called whenever a click on the RaisedButton instantiated by _ParentWidgetState is performed.

    0 讨论(0)
提交回复
热议问题