1

我不知道要查找什么,所以请随时给我一些关于在哪里查找的指示。我正在学习,所以这绝对值得赞赏。

我刚刚发现我可以在颤动中使用命名路由,并且我正试图转向事物以使我的应用程序的行为更可预测。但是,在某些时候,我的 UserDataContainer Stateful Widget 会丢失他的状态值。所以我有一些用户数据,它消失了。

这是一些代码。

这是我的用户数据容器:

// app_state_container.dart
//import 'package:advanced_app/models/app_state.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:myapp/FoodLib/user.dart';

class UserDataContainer extends StatefulWidget {
// Your apps state is managed by the container
  final UserDataType userdata = UserDataType();
// This widget is simply the root of the tree,
// so it has to have a child!
  final Widget child;

  UserDataContainer({@required this.child
//    @required this.userdata,
      }) {
    print("CREATED USERDATA CONTAINER");
    print("The name: " + this.userdata.name);
  }

// This creates a method on the AppState that's just like 'of'
// On MediaQueries, Theme, etc
// This is the secret to accessing your AppState all over your app
  static _UserDataContainerState of(BuildContext context) {
    return (context.inheritFromWidgetOfExactType(_InheritedUserDataContainer)
            as _InheritedUserDataContainer)
        .data;
  }

  @override
  _UserDataContainerState createState() => new _UserDataContainerState();
}

class _UserDataContainerState extends State<UserDataContainer> {
// Just padding the state through so we don't have to
// manipulate it with widget.state.
//  UserDataType userdata  = UserDataType();

  String name = "test";

  @override
  void initState() {
// You'll almost certainly want to do some logic
// in InitState of your AppStateContainer. In this example, we'll eventually
// write the methods to check the local state
// for existing users and all that.
    super.initState();
  }

// So the WidgetTree is actually
// AppStateContainer --> InheritedStateContainer --> The rest of your app.
  @override
  Widget build(BuildContext context) {
    return new _InheritedUserDataContainer(
      data: this,
      child: widget.child,
    );
  }
}

// This is likely all your InheritedWidget will ever need.
class _InheritedUserDataContainer extends InheritedWidget {
// The data is whatever this widget is passing down.
  final _UserDataContainerState data;

// InheritedWidgets are always just wrappers.
// So there has to be a child,
// Although Flutter just knows to build the Widget thats passed to it
// So you don't have have a build method or anything.
  _InheritedUserDataContainer({
    Key key,
    @required this.data,
    @required Widget child,
  }) : super(key: key, child: child);

// This is a better way to do this, which you'll see later.
// But basically, Flutter automatically calls this method when any data
// in this widget is changed.
// You can use this method to make sure that flutter actually should
// repaint the tree, or do nothing.
// It helps with performance.
  @override
  bool updateShouldNotify(_InheritedUserDataContainer old){
    if(
    data.widget.userdata.fooditems.length !=
        old.data.widget.userdata.fooditems.length){
      return true;

    }
//    print("SAME");
    return false;
  }
}

UserDataType包含消失数据的类在哪里。

这是我的 Material 类的主要应用程序:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new DynamicTheme(
        defaultBrightness: Brightness.light,
        data: (brightness) => new ThemeData(
              primarySwatch: Colors.teal,
              brightness: brightness,
            ),
        themedWidgetBuilder: (context, theme) {
          return UserDataContainer(
            child: MaterialApp(
              title: 'Title',
              home: UserLoader(),
              theme: theme,

              routes: {
                // When navigating to the "/" route, build the FirstScreen widget.
                '/userpage': (context) => User(),
                '/settings': (context) => SettingsPage(),
                '/saved_stuff' : (context) => SavedRecipesPage(),
                '/database' : (context) => Database(),
                '/new_list' : (context) => ShoppingKartPage(),
                '/stats' : (context) => StatPage(),
                // When navigating to the "/second" route, build the SecondScreen widget.
//                '/second': (context) => SecondScreen(),
              },

            ),
          );
        });
  }
}

class UserLoader extends StatelessWidget {
  @override




  Widget build(BuildContext context) {
    print("Version 1");

    final ThemeData theme = Theme.of(context);

    return FutureBuilder<void>(
        future: UserDataContainer.of(context).widget.userdata.init(),
        builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            print("Build user");




            return User();
          } else {
            return SplashScreen();
          }
        });
  }
}

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => new _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Center(
        child: new Image.asset('images/icon.png'),
      ),
    );
  }
}

材料应用程序有我的路线,并且 UserLoader 在那里,所以我可以在启动时加载保存在手机上的一些用户数据。它会放置一个启动屏幕并等待数据加载。

在我的抽屉中,我已经用命名版本替换了代码以移动到特定页面:

Navigator.push(
      context,
      MaterialPageRoute(
          builder: (context) => SettingsPage()));

成为

Navigator.of(context).pop();

例如。

但是,现在当我使用该应用程序时,UserDataContainer 有时包含一个全新的 User() 实例(这是一个 dart 类,而不是一个小部件),我不知道为什么应用程序会突然出现这样的行为。

编辑:

我尝试通过使用它而不是我的 futureloader 来删除 FutureBuilder,但 UserContainer 的状态每次都会重新生成(虽然没有再次被初始化):

class LoadingScreen extends StatefulWidget {
  @override
  _LoadingScreenState createState() => new _LoadingScreenState();

}

class _LoadingScreenState extends State<LoadingScreen>{

  @override
  void initState() {
    super.initState();

    SchedulerBinding.instance.addPostFrameCallback((_){
      runInitTasks();
    });


  }

  @protected
  Future runInitTasks() async {
    await UserDataContainer.of(context).widget.userdata.init();

    Navigator.of(context).pushReplacementNamed('/fridge');
  }

  @override
  Widget build(BuildContext context){
    return Scaffold(
      body: new Center(
        child: new Image.asset('images/icon.png'),
      ),
    );
  }
}
4

1 回答 1

0

在导航上丢失数据的原因是因为一旦导航到屏幕就会被重建。使用shared_preferences可以轻松跟踪简单数据,但如果您想拥有更大的灵活性,可以使用状态管理实现,例如使用提供程序插件。这是文档中提供的有关如何使用提供程序的示例。

于 2021-12-23T04:40:22.650 回答