How to pass data by reference to stateful widget? I want to change a variable inside a stateful widget and update original variable
3,553
Actually the StatefulWidget
is immutable and its state is maintained by the State
class. You cannot pass values by reference and update the widgets. Instead you can just pass the value and and a function that updates the value.
Example:
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,
),
],
),
);
}
}
Hoper that helps!
Author by
tmaihoff
Updated on December 12, 2022Comments
-
tmaihoff over 1 year
I want to pass data to a stateful widget, change the data inside the widget and also have it updated in the original location.
I want to avoid global variables and I am wondering if I can pass a variable to a stateful widget by reference.
Here is some example code where data is passed to the widget. If I use the slider, the counter is only update inside the widget, not in the main layout tree.
I appreciate any help.
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), ])); } }