简体   繁体   中英

Call method of a widget from another widget

I just started flutter, this is a basic question but I am not able to solve. I created a stateful widget and I need to call the setState() method on click of a button. The button is not part of this stateful widget. The button is present in the footer of application.

complete application code:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  build(BuildContext context) {
    return new MaterialApp(
        title: "My app title",
        home: new Scaffold(
          appBar: new AppBar(
            title: new Text("My App"),
            backgroundColor: Colors.amber,
          ),
          body: new Container(
            child: new Center(
              child: new MyStateFullWidget(),
            ),
          ),
          persistentFooterButtons: <Widget>[
            new FlatButton(
              onPressed: () {
                // I need to call the update() of MyStateFullWidget/MyStateFullWidgetState class
              },
              child: new Text("Click Here"),
              color: Colors.amber,
              textColor: Colors.white,
            ),
          ],
        ));
  }
}

class MyStateFullWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new MyStateFullWidgetState();
  }
}

class MyStateFullWidgetState extends State<MyStateFullWidget> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return new Text("Count: $count");
  }

  update() {
    setState() {
      count++;
    }
  }
}

I need to call the setState() method on click of a button

You may have a few options (or alternatives) to achieve the end result (all with different tradeoffs):

  • Elevate the state (ie count ) to an Inherited Widget above the Button and Display Widget. This may be the easiest or most appropriate.
  • Leverage some kind of Action-based communication such as Flutter Redux (where you dispatch an action, which affects the display widget via a StoreConnector and rebuilds). This can be seen as just another way to 'elevate' state. However, this requires a whole new dependency and a lot of overhead given your simple example, but I wanted to point it out.
  • You can create some kind of Stream and StreamController that the Display widget subscribes/listens to. However, this may be overkill and I'm not sure how appropriate representing button clicks over a stream would be.

There may be other solutions that I'm not thinking of; however, remember that the goal of reactive UI is to keep state simple .

So if you have multiple leaf widgets that care about a piece of state (want to know it, want to change it), it might mean that this belongs to a higher level component (eg a App-level piece of state, or maybe some other common ancestor - but both could use Inherited Widget to prevent passing the piece of state all around)

You should use your Scaffold in the State instead of using in StatelessWidget . Here is the working solution.

class MyApp extends StatelessWidget {
  @override
  build(BuildContext context) {
    return MaterialApp(
        title: "My app title",
        home: MyStateFullWidget());
  }
}

class MyStateFullWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyStateFullWidgetState();
  }
}

class MyStateFullWidgetState extends State<MyStateFullWidget> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("My App"),
        backgroundColor: Colors.amber,
      ),
      body: Container(
        child: Center(
          child:Text("Count: $count"),
        ),
      ),
      persistentFooterButtons: <Widget>[
        FlatButton(
          onPressed: update,
          child: Text("Click Here"),
          color: Colors.amber,
          textColor: Colors.white,
        ),
      ],
    );
  }

  void update() {
    setState(() {
      count++;
    });
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM