【问题标题】:Flutter: how to call setState() in onPressed() from separate Widget methodFlutter:如何从单独的 Widget 方法调用 onPressed() 中的 setState()
【发布时间】:2019-07-23 12:45:43
【问题描述】:

我是这个Flutter的新手

我正在尝试更改 FlatButton 文本,而 onPressed。我的页面设计在单独的Widget 方法中,所以无法在onPressed 中添加setState()

我搜索了很多。但是,没找到。请帮我解决这个问题。

import 'package:flutter/material.dart';

int number = 10;

class SecondRoute extends StatelessWidget {
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Lists'),
        backgroundColor: new Color(0xFF000000),
      ),
      body: DynamicChange(),
    );
  }
}

class DynamicChange extends StatefulWidget {
  @override
  StateDynamic createState() => StateDynamic();
} // Class SecondRoute

class StateDynamic extends State<DynamicChange> {
  Widget build(BuildContext context) {
    return new Scaffold(
      body: thisScreenNeeds(),
    );
  }
}

Widget thisScreenNeeds() {
  return Container(
    margin: EdgeInsets.only(top: 100, left: 50),
      child: FlatButton(
    child: Text(
      number.toString(),
      textAlign: TextAlign.center,
      style: (TextStyle(
          fontWeight: FontWeight.bold, fontSize: 60, color: Colors.green)),
    ),
    onPressed: () {
       // Unable to add, setState(). Throwing error.
    },
  ));
}

尝试 1

onPressed: () {
      // Error: The member 'setState' can only be used within instance members of subclasses
      StateDynamic().setState(() {
        number = number + 1;
   });
},

尝试 2

class StateDynamic extends State<DynamicChange> {

.....
.........

void _incrementCounter() {
    setState(() {
      number++;
    });
  }

.....
.......

}

onPressed: StateDynamic()._incrementCounter,

// Run Time Error: 
   This happens when you call setState() on a State object for a 
   widget that hasn't been inserted into the widget tree yet. 
   It is not necessary to call setState() in the constructor, 
   since the state is already assumed to be dirty when it is 
   initially created.

【问题讨论】:

    标签: flutter dart flutter-layout


    【解决方案1】:

    将方法保留在State 类中。也最好将 number 变量也保留在该类中。您只能在 State 类中直接 setState,这就是原因。

    在你的情况下,解决方案

    class SecondRoute extends StatelessWidget {
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text('Lists'),
            backgroundColor: new Color(0xFF000000),
          ),
          body: DynamicChange(),
        );
      }
    }
    
    class DynamicChange extends StatefulWidget {
      @override
      StateDynamic createState() => StateDynamic();
    } // Class SecondRoute
    
    class StateDynamic extends State<DynamicChange> {
      int number = 10;
    
      Widget build(BuildContext context) {
        return new Scaffold(
          body: thisScreenNeeds(),
        );
      }
    
      Widget thisScreenNeeds() {
        return Container(
            margin: EdgeInsets.only(top: 100, left: 50),
            child: FlatButton(
              child: Text(
                number.toString(),
                textAlign: TextAlign.center,
                style: (TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 60,
                    color: Colors.green)),
              ),
              onPressed: () {
                setState(() {
                  number++;
                });
              },
            ));
      }
    }
    

    如果您需要完全分离小部件(据我所知),您可以通过构造函数发送VoidCallback 参数。喜欢:

    class App extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Home(),
        );
      }
    }
    
    class Home extends StatefulWidget {
      @override
      _HomeState createState() => _HomeState();
    }
    
    class _HomeState extends State<Home> {
      String text = 'Some text';
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Text(text),
              ButtonWidget(stateSetter),
            ],
          ),
        );
      }
    
      void stateSetter() {
        setState(() {
          text = 'Changed text';
        });
      }
    }
    
    class ButtonWidget extends StatelessWidget {
      final VoidCallback stateSetter;
    
      ButtonWidget(this.stateSetter);
    
      @override
      Widget build(BuildContext context) {
        return RaisedButton(
          onPressed: this.stateSetter,
        );
      }
    }
    

    【讨论】:

    • Widget thisScreenNeeds() { return Container();},我为 Button 使用了单独的小部件。它会起作用吗?
    • 试试看。回调在开始时可能会令人困惑,但这很容易。
    • Widget thisScreenNeeds() { return Container();} ,这样是不是错了?
    • @McDonal_11 是的,抱歉,我没有完整阅读您的问题,主要根据主题回答,解决方案实际上很简单。我现在就分享。
    • 那么,代替 Widget thisScreenNeeds()class ButtonWidget extends StatelessWidget {} ,这种方式合适吗?请在此澄清一下。
    猜你喜欢
    • 1970-01-01
    • 2023-01-04
    • 1970-01-01
    • 1970-01-01
    • 2019-01-19
    • 2023-02-18
    • 1970-01-01
    • 2019-11-21
    • 2021-11-11
    相关资源
    最近更新 更多