如何通过引用有状态小部件来传递数据?我想更改有状态小部件中的变量并更新原始变量

Posted

技术标签:

【中文标题】如何通过引用有状态小部件来传递数据?我想更改有状态小部件中的变量并更新原始变量【英文标题】:How to pass data by reference to stateful widget? I want to change a variable inside a stateful widget and update original variable 【发布时间】:2019-11-27 14:25:59 【问题描述】:

我想将数据传递给有状态的小部件,更改小部件内的数据并在原始位置更新它。

我想避免使用全局变量,我想知道是否可以通过引用将变量传递给有状态的小部件。

这是一些将数据传递给小部件的示例代码。如果我使用滑块,计数器只会在小部件内部更新,而不是在主布局树中。

感谢您的帮助。

import 'package:flutter/material.dart';
void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);
  final String title;

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


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

  void _incrementCounter() 
    setState(() 
      _counter++;
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'Counter inside main layout tree: $_counter',
              style: Theme.of(context).textTheme.title,
            ),
            TestWidget(_counter),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  


class TestWidget extends StatefulWidget 
  int counter;
  TestWidget(this.counter);
  @override
  _TestWidgetState createState() => _TestWidgetState();


class _TestWidgetState extends State<TestWidget> 
  @override
  Widget build(BuildContext context) 
    return Card(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.all(Radius.circular(10)),
          side: BorderSide(color: Colors.orange),
        ),
        child: Column(children: <Widget>[
          Text("This card is an external Widget"),
          Slider(
            min: 0,
            max: 100,
            divisions: 101,
            onChanged: (double val) 
              setState(() 
                widget.counter = val.toInt();
              );
            ,
            value: widget.counter.toDouble(),
          ),
          Text("Counter inside external widget: $widget.counter",
              style: Theme.of(context).textTheme.title),
        ]));
  
    

【问题讨论】:

【参考方案1】:

实际上StatefulWidget 是不可变的,其状态由State 类维护。您不能通过引用传递值并更新小部件。相反,您可以只传递值和更新值的函数。

例子:

class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);
  final String title;

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


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

  void _incrementCounter([int value]) 
    setState(() 
      _counter = value ?? (_counter + 1);
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'Counter inside main layout tree: $_counter',
              style: Theme.of(context).textTheme.title,
            ),
            TestWidget(
              counter: _counter,
              updateCount: _incrementCounter,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  


class TestWidget extends StatelessWidget 
  final int counter;
  final ValueChanged<int> updateCount;

  const TestWidget(Key key, this.counter, this.updateCount) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(10)),
        side: BorderSide(color: Colors.orange),
      ),
      child: Column(
        children: <Widget>[
          Text("This card is an external Widget"),
          Slider(
            min: 0,
            max: 100,
            divisions: 101,
            onChanged: (double val) 
              updateCount(val.toInt());
            ,
            value: counter.toDouble(),
          ),
          Text(
            "Counter inside external widget: $counter",
            style: Theme.of(context).textTheme.title,
          ),
        ],
      ),
    );
  

希望有帮助!

【讨论】:

以上是关于如何通过引用有状态小部件来传递数据?我想更改有状态小部件中的变量并更新原始变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在有状态小部件之间传递随机数据?

Flutter - 无法从父小部件更改子状态

如何从另一个小部件更改有状态小部件的变量?

如何从有状态的小部件类传递变量? - 颤动[重复]

有状态与无状态的区别如何影响小部件何时重建?

如何通过单击放置在同一页面上的小部件来显示不同的小部件