flutter int got to zero

364

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

Share:
364
Mhmd Khatib
Author by

Mhmd Khatib

Updated on December 27, 2022

Comments

  • Mhmd Khatib
    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
      Scott Godfrey about 3 years
      So, basically the issue is it's going back to zero?
    • fartem
      fartem about 3 years
      You 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
      Mhmd Khatib about 3 years
      @ScottGodfrey, exactly
    • Scott Godfrey
      Scott Godfrey about 3 years
      When 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
    Mhmd Khatib about 3 years
    thanks, 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
    Loren.A about 3 years
    Just 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.