如何在 Flutter 中使用全局键制作 StatefulWidget?

Posted

技术标签:

【中文标题】如何在 Flutter 中使用全局键制作 StatefulWidget?【英文标题】:How to make StatefulWidget with global key in Flutter? 【发布时间】:2021-07-24 01:36:04 【问题描述】:

我是 Flutter 的新手,我想我可能只是设置了一些奇怪的东西。到目前为止的大部分设置都来自小型教程。我目前的 main.dart 只呈现一个 userCheck 小部件,最终将用于连接后端并检查我是否拥有有效的用户令牌。

class UserCheck extends StatefulWidget 
  const UserCheck(Key key) : super(key: key);

  @override
  UserCheckState createState() => UserCheckState();


class UserCheckState extends State<UserCheck> 
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  var userExists = false;

  @override
  Widget build(BuildContext context) 
    return userExists
        ? Home()
        : new LoginForm();
  

如果有合适的用户,Home Widget 最终会从后端加载信息。现在,userExists 显然默认为 false。这可以很好地加载 LoginForm。我目前的目标是当用户登录时,假设它是一个很好的登录,然后将 userExists 反转为 true,从而打开主页。这是 LoginForm 设置:

  LoginForm(Key key) : super(key: key);
  UserCheckState parent;

  @override
  LoginFormState createState() => LoginFormState();


class LoginFormState extends State<LoginForm> 
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  var userData = ;
  bool login = true;
  String loginText = 'Sign Up';

  void updateField(String value, String field) 
    setState(() 
      userData = 
        ...userData,
        '$field': value,
      ;
    );
  

  void sendHome() 
    setState(() 
      // this.parent.parent.userExists = true;
    );
  

  @override
  Widget build(BuildContext context) 
    return Container(
      child: Column(children: <Widget>[
        login
            ? Form(
                key: _formKey,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    TextFormField(
                      decoration: const InputDecoration(
                          hintText: 'Enter a username', labelText: 'Username'),
                      validator: (String value) 
                        if (value == null || value.isEmpty) 
                          return 'Please enter a username';
                        
                        updateField(value, 'username');
                        return null;
                      ,
                    ),
                    TextFormField(
                      obscureText: true,
                      enableSuggestions: false,
                      autocorrect: false,
                      decoration: const InputDecoration(
                          hintText: 'Enter your password',
                          labelText: 'Password'),
                      validator: (String value) 
                        if (value == null || value.isEmpty) 
                          return 'Please enter a password';
                        
                        updateField(value, 'password');
                        return null;
                      ,
                    ),
                    Padding(
                      padding: const EdgeInsets.symmetric(vertical: 16.0),
                      child: ElevatedButton(
                        onPressed: () 
                          print('hit here');
                          if (_formKey.currentState.validate()) 
                            print('hit here two');
                            sendHome();
                            print(userData);
                            // if API responds with proper token

                            // API call to login
                          
                        ,
                        child: Text('Submit'),
                      ),
                    ),
                  ],
                ),
              )
            : SignupForm(),
        ElevatedButton(
          onPressed: () 
            setState(() 
              login = !login;
              loginText = loginText == 'Sign Up' ? 'Log In' : 'Sign Up';
            );
          ,
          child: Text(loginText),
        )
      ]),
    );
  
```

I don't know if there's some sort of router that would be better and is already implemented as switching Widgets, but I haven't found anything from my own searches.

【问题讨论】:

为了更好的代码可维护性和效率,我强烈建议您使用状态管理系统来为您做到这一点。检查this,它会让您的生活更轻松。 【参考方案1】:

如果用户登录,您不必返回userCheck 小部件。相反,您可以使用Navigator 直接转到Home 屏幕,从Login 页面进行转换到Home 页面。将导航器放在用户在您的Submit 按钮的onPressed 函数内获得有效令牌的行之后:

ElevatedButton(
  onPressed: () 
    if (_formKey.currentState.validate()) 
      // Goes to Home screen.
      Navigator.of(context).push(MaterialPageRoute(
        builder: (context) => Home(),
      ));
    
  ,
  child: Text('Submit'),
),

【讨论】:

以上是关于如何在 Flutter 中使用全局键制作 StatefulWidget?的主要内容,如果未能解决你的问题,请参考以下文章

flutter : 如何在颤动中制作卡片

如何在 Flutter 中创建和使用 SnackBar 进行重用(全局)

如何在 Flutter 中使用路由制作持久抽屉?

如何在 Flutter 中制作带背景的抠图图标?

Flutter 如何在 Android Studio 中制作发布版本?

如何在 Flutter 中制作密码验证动画