flutter int got to zero
Solution 1
To expand on what @nvoigt said, pick a state management solution instead of passing around arguments from page to page. This way you can keep your widgets stateless, which is preferred but not possible to do what you want to do without a state management solution.
Here's a quick way using GetX state management. This can be done using Provider, RiverPod, Bloc/Cubit...pick your poison.
Here's a new controller class with your data and logic.
class DataController extends GetxController {
int data = 0;
void eins() {
data += 25;
update();
}
}
Then a couple small changes to the rest of your good and you're good to go.
void main() {
Get.put(DataController()); // initializing your controller
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/menu',
onGenerateRoute: RouteGenerator.generateRoute,
);
}
}
class Menu extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Menu'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
RaisedButton(
onPressed: () {
Navigator.of(context).pushNamed('/second');
},
child: Text('go to the second'),
),
],
),
));
}
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = Get.find<DataController>(); // finding controller
return Scaffold(
appBar: AppBar(
title: Text('First Page'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
GetBuilder<DataController>( // wrap your text in GetBuilder to display variabe
builder: (_) {
return Text(
controller.data.toString(), // accessing variable via controller
);
},
),
RaisedButton(
onPressed: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/second');
},
child: Text('go to the second'),
),
RaisedButton(
child: Text('25'),
onPressed: () {
controller.eins(); // accessing function via controller
}),
],
),
));
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = Get.find<DataController>(); // finding same instance of controller on new page
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
GetBuilder<DataController>(
builder: (_) {
return Text(
controller.data.toString(),
);
},
),
RaisedButton(
onPressed: () {
Navigator.of(context).pushNamed('/first');
},
child: Text('go to the first'),
),
],
),
));
}
}
// no longer need to pass anything in your router below
class RouteGenerator {
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case '/first':
return MaterialPageRoute(
builder: (_) => FirstPage(),
);
case '/third':
return MaterialPageRoute(
builder: (_) => FirstPage(),
);
case '/menu':
return MaterialPageRoute(
builder: (_) => Menu(),
);
case '/second':
// if (args is int) {
return MaterialPageRoute(
builder: (_) => SecondPage(),
);
//}
// return _errorRoute();
//default:
//return _errorRoute();
}
}
Solution 2
The first thing that is weird about your program is that you want to preserve state, in your case a counter variable, but to do that, you select a StatelessWidget. At the very least you will need a StatefulWidget. It's in the name already.
That said, it's not that easy, you may want to look up the different approaches to state management in Flutter: https://flutter.dev/docs/development/data-and-backend/state-mgmt/options
Mhmd Khatib
Updated on December 27, 2022Comments
-
Mhmd Khatib over 1 year
I have a screen with a one button and anotherone with a Container to show a number. I declared a variable in the StatlessWidget class. The button adds 1 to the variable , however after leaving the Class with the container und return to it, I noticed the widgets get updated and my variable loses its value. I have tried initializing it in initState() but it still loses it's value.
import 'package:flutter/material.dart'; import 'package:generator/route_generator.dart'; import 'package:generator/main.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), initialRoute: '/menu', onGenerateRoute: RouteGenerator.generateRoute, ); } } class Menu extends StatelessWidget { int data = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Menu'), ), body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ RaisedButton( onPressed: () { Navigator.of(context).pushNamed('/second', arguments: data); }, child: Text('go to the second'), ), ], ), )); } } class FirstPage extends StatelessWidget { int data = 0; void eins() { data = data + 25; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('First Page'), ), body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( data.toString(), ), RaisedButton( onPressed: () { Navigator.pop(context); Navigator.of(context).pushNamed('/second', arguments: data); }, child: Text('go to the second'), ), RaisedButton( child: Text('25'), onPressed: eins, ) ], ), )); } } class SecondPage extends StatelessWidget { int data = 0; SecondPage({Key key, @required this.data}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Second Page'), ), body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( data.toString(), style: TextStyle(fontSize: 20), ), RaisedButton( onPressed: () { Navigator.of(context).pushNamed('/first'); }, child: Text('go to the first'), ), ], ), )); } }
another class
import 'package:flutter/material.dart'; import 'package:generator/main.dart'; import './main.dart'; class RouteGenerator { static Route<dynamic> generateRoute(RouteSettings settings) { final args = settings.arguments; switch (settings.name) { case '/first': return MaterialPageRoute( builder: (_) => FirstPage(), ); case '/third': return MaterialPageRoute( builder: (_) => FirstPage(), ); case '/menu': return MaterialPageRoute( builder: (_) => Menu(), ); case '/second': // if (args is int) { return MaterialPageRoute( builder: (_) => SecondPage( data: args, ), ); //} // return _errorRoute(); //default: //return _errorRoute(); } } static Route<dynamic> _errorRoute() { return MaterialPageRoute(builder: (_) { return Scaffold( appBar: AppBar( title: Text('Error'), ), body: Center( child: Text('ERROR'), ), ); }); } }
-
Scott Godfrey about 3 yearsSo, basically the issue is it's going back to zero?
-
fartem about 3 yearsYou need to store you value in a global object. It may be a global variable (a variable that declared outside of a class).
-
Mhmd Khatib about 3 years@ScottGodfrey, exactly
-
Scott Godfrey about 3 yearsWhen your widget gets rebuilt (Such as when coming from another page/widget) then the int data = 0; will get triggered again. So, it gets reset back to zero. When you store your variable inside a widget, it's difficult to manage the state from another widget, especially a stateless widget. @JamesA has a great example of how it would work using an external (External to the UI) state management library.
-
-
Mhmd Khatib about 3 yearsthanks, that did work @JamesA. How should it be, if i have a third page with a button, that ads another value to my var.
-
Loren.A about 3 yearsJust add another function that adds the required value to your GetX Controller class. Access the controller and fire that function the same way I showed in my example.