I'm trying to build an app using Flutter and am running into a small problem. I'm trying to implement a BottomNavigaionBar style app with three pages. (see first snippet) The layout makes use of three objects of type "ChorePage". It seems like the app is creating three instances of ChorePage, but only one instance of _ChorePageState.
This causes the variable _dataRows to be shared between the three tabs meaning I can't put different information into the different tabs. Why is this happening and how do I prevent it?
I have put print statements into the createState() function and am printing the 'this' variable in the PopulateRows function which is called on every rebuild of the ChorePage. The print output is seen below and confirms that indeed the three widgets use the same State object. (createState is only called once for object A and the this variable refers to the same object)
class AppLayout extends StatefulWidget {
@override
_AppLayoutState createState() => _AppLayoutState();
}
class _AppLayoutState extends State<AppLayout> {
int _currentIndex = 0;
String title = 'Test';
List<Widget> _children = [
new ChorePage(Title:'A'),
new ChorePage(Title:'B'),
new ChorePage(Title:'C')
];
@override
Widget build(BuildContext context) {
//STUFF BEFORE INIT
return Scaffold(
appBar: AppBar(
title: Text('$title'),
),
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
items:[
BottomNavigationBarItem(
icon: Icon(MdiIcons.sprayBottle),
title:Text('Menu1'),
),
BottomNavigationBarItem(
icon: Icon(MdiIcons.glassMugVariant),
title:Text('Menu2'),
),
BottomNavigationBarItem(
icon: Icon(Icons.event_note),
title:Text('Menu3'),
)
]
),
);
}
void onTabTapped(int index){
setState(() {
_currentIndex = index;
});
}
}
ChorePage
class ChorePage extends StatefulWidget {
final String Title;
const ChorePage({Key key, this.Title}): super(key: key);
@override
_ChorePageState createState() {
print('Creating: '+this.Title);
return new _ChorePageState();
}
}
class _ChorePageState extends State<ChorePage> {
List<DataRow> _dataRows = [];
@override
Widget build(BuildContext context) {
PopulateRows();
return SingleChildScrollView(
child:Center(
child: DataTable(
columns: [
DataColumn(label: Text(widget.Title.toString())),
DataColumn(label: Text('Col1')),
DataColumn(label: Text('Col2')),
],
rows: _dataRows,
),
),
);
}
void PopulateRows(){
print(this);
print(widget.Title.toString());
//_dataRows = [];
for(int i=0;i<1;i++) {
DataRow R = DataRow(cells:[]);
R.cells.add(DataCell(Text(widget.Title)));
R.cells.add(DataCell(Text(i.toString())));
R.cells.add(DataCell(Text((i + 1).toString())));
_dataRows.add(R);
}
}
}
Print Output:
Installing build\app\outputs\apk\app.apk...
Debug service listening on ws://127.0.0.1:59033/TvJtQ-PN3a8=/ws
Syncing files to device Mi 9T Pro...
I/flutter (28856): Creating: A
I/flutter (28856): _ChorePageState#d1d35
I/flutter (28856): A
I/xxxxxxx.tms_ap(28856): ProcessProfilingInfo new_methods=403 is saved saved_to_disk=1 resolve_classes_delay=8000
I/flutter (28856): _ChorePageState#d1d35
I/flutter (28856): B
I/flutter (28856): _ChorePageState#d1d35
I/flutter (28856): C
Steps to Pass Data to Stateful Widget in Flutter To pass data to stateful widget, first of all, create two pages. Now from the first page open the second page and pass the data. Inside the second page, access the variable using the widget. For example widget.
Struggled with what I think is the same issue today and the solution ended up being to pass a String key to the StatefulWidget constructor. So in your example:
List<Widget> _children = [
new ChorePage(key: Key('A'), Title:'A'),
new ChorePage(key: Key('B'), Title:'B'),
new ChorePage(key: Key('C'), Title:'C')
];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With