为什么Flutter rerender小部件包含一个带有自己键的TextFormField?

时间:2019-02-07 14:46:23

标签: forms dart flutter navigator form-fields



    Doctor summary (to see all details, run flutter doctor -v):
    [v] Flutter (Channel dev, v1.2.0, on Microsoft Windows [Version 10.0.17763.253], locale ru-RU)
    [v] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    [v] Android Studio (version 3.3)
    [v] VS Code, 64-bit edition (version 1.30.2)
    [v] Connected device (1 available)

    • No issues found!

你好!我在家学习flutter来创建我的应用程序,并且面对flutter的不可理解性-当我在导航器的任何路线上使用任何小部件中的字段创建表单时,都可以在formfield上点击并关闭键盘时看到这种路线的重建。如果我删除GlobalKey并删除GlobalKey-窗口小部件确实可以在点击时重建,并且仍然隐藏键盘,在这种情况下不会感到不适,但是如果我想赋予表单和带有globalKeys的此字段-在与字段的任何交互下,我都看到该表单正在破坏并一次又一次地建造。



    import 'package:flutter/material.dart';
    import 'package:flutter_mobx/flutter_mobx.dart';
    import 'package:quich/controllers/user_controller.dart';
    import 'package:quich/route/routes.dart';
    import 'package:quich/screens/login_screen.dart';
    import 'package:quich/screens/splash_screen.dart';
    import 'package:quich/store/app_store.dart';

    void main() async {
      runApp(Quich());
      await $store.storage.ready;
      var uc = UserController();
      var isValid = await uc.isTokenValid(token: 'token');
      $store.isAuth = isValid;
      $store.isLoading = false;
    }

    class Quich extends StatefulWidget {
      @override
      State createState() => _QuichState();
    }

    class _QuichState extends State {
      final controller = TextEditingController();
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Регистрация',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          initialRoute: Routes.splash,
          routes: {
            Routes.splash: (context) => Observer(builder: (_) {
              return SplashScreen();
            }),
            Routes.login: (context) {
              print('SUPER PARENT BUILD');
              return LoginScreen();
              final formKey = GlobalKey();
              final fieldKey = GlobalKey();
              return Scaffold(
                body: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Form(
                      child: Padding(
                        padding: const EdgeInsets.all(15.0),
                        child: TextFormField(
                          controller: controller,
                          key: fieldKey
                        ),
                      ),
                      key: formKey,
                    ),
                    ButtonBar(
                      children: [
                        MaterialButton(
                          child: Text('Проверка', style: TextStyle(color: Colors.white)),
                          onPressed: () => Navigator.of(context).pushNamed(Routes.splash),
                          color: Colors.lightBlue,
                        )
                      ],
                    )
                  ],
                ),
              );
            }
          },
        );
      }
    }

能帮我在Navigator的内部创建带有带有全局键的字段的表单吗?-我搜索了带有表单和导航的示例,但是在我没有找到的导航器中搜索了带有globalKeys的表单;

UPD:似乎StackOverflow代码编辑器“吃”了一些代码部分的定义。我在图片上附加了代码,请查看视频示例:

Video 1

Video 2

Image with code

Ru-copy of this topic

P.S。问题解决了,如果您有兴趣,可以解决这个问题-可以在此问题的俄语副本的“ P.P.S”块中看到: Russian Copy

2 个答案:

答案 0 :(得分:1)

我发现您在扩展类时没有使用适当的通用方式,

 class _QuichState extends State<Quich>{}

试试这个, 接下来,给您一个示例代码,以便您可以匹配

中的代码
   return Form(
  key: _formKey,
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
      TextFormField(
        validator: (value) {
          if (value.isEmpty) {
            return 'Please enter some text';
          }
        },
      ),
      Padding(
        padding: const EdgeInsets.symmetric(vertical: 16.0),
        child: RaisedButton(
          onPressed: () {
            // Validate will return true if the form is valid, or false if
            // the form is invalid.
            if (_formKey.currentState.validate()) {
              // If the form is valid, we want to show a Snackbar
              Scaffold.of(context)
                  .showSnackBar(SnackBar(content: Text('Processing Data')));
            }
          },
          child: Text('Submit'),
        ),
      ),
    ],
  ),
);

此后,创建一个全局密钥,该密钥将唯一地标识Form小部件并允许    我们来验证表格或其他活动

注意:这是一个GlobalKey,而不是GlobalKey!

  final _formKey = GlobalKey<FormState>();

答案 1 :(得分:0)

在抖动key中,属性用于将窗口小部件的现有实例与新实例进行比较,并确定下一步要做什么:创建新状态或使用现有状态,构建新的子树或重用现有的状态。如果未提供键,则flutter将使用小部件树中小部件的位置作为键。如果树的结构变化不大,那么只有很小的变化,状态或子树很有可能被重用。

GlobalKey()的想法是,您创建它的一个实例并将其最有可能保存在应用程序树层次结构中的某个较高位置。

GlobalKey()的帮助下,只要以下条件,就可以重用小部件的状态和子树:

  • 您保留了GlobalKey()的同一实例
  • 您的窗口小部件未完全从树中删除。如果删除了小部件,则其状态和子树将消失,下一次进入应用程序的树状状态时,将重新创建子树。

在代码示例中,您没有将GlobalKey()分配给可重用变量。在您的情况下,将在构建函数内创建Globalkey()的新实例。这将导致在每次更新时创建新的唯一密钥。新的唯一键意味着该窗口小部件未链接到该窗口小部件的先前实例,因此没有状态且没有子树被继承。