flutter int 归零

flutter int got to zero

我有一个带有一个按钮的屏幕和另一个带有用于显示数字的容器的屏幕。我在 StatlessWidget class 中声明了一个变量。该按钮将 1 添加到变量,但是在将 Class 与容器和 return 一起保留后,我注意到小部件得到更新并且我的变量失去了它的值。我已经尝试在 initState() 中初始化它,但它仍然失去了它的价值。

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'),
              ),
            ],
          ),
        ));
  }
}

另一个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'),
        ),
      );
    });
  }
}

关于您的程序的第一件事是您想要保留 state,在您的情况下是一个计数器变量,但要做到这一点,您 select一个 StatelessWidget。至少您需要一个 StatefulWidget。已经在名字里了。

也就是说,这并不容易,您可能需要查找 Flutter 中状态管理的不同方法:https://flutter.dev/docs/development/data-and-backend/state-mgmt/options

要扩展@nvoigt 所说的内容,请选择一个状态管理解决方案,而不是在页面之间传递参数。通过这种方式,您可以让您的小部件保持无状态,这是首选,但如果没有状态管理解决方案,您将无法做您想做的事情。

这是使用 GetX state management 的快速方法。这可以使用 Provider、RiverPod 来完成,Bloc/Cubit...选择你的毒药。

这是一个包含您的数据和逻辑的新控制器class。

class DataController extends GetxController {
  int data = 0;
  void eins() {
    data += 25;
    update();
  }
}

然后对您的其余部分进行一些小改动,您就可以开始了。

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();
    }
  }