Forms 为什么颤振重渲染器小部件包含一个具有自己密钥的TextFormField?

Forms 为什么颤振重渲染器小部件包含一个具有自己密钥的TextFormField?,forms,dart,flutter,navigator,form-fields,Forms,Dart,Flutter,Navigator,Form Fields,我在家里学习颤振来创建我的应用程序,面临着颤振的不可理解性;当我在导航器的任何路径的任何小部件中创建一个带有字段的表单时,我在点击formfield和关闭键盘时看到了该路径的重建。如果我移除GlobalKey并移除GlobalKey-小部件在点击并隐藏键盘时仍然重建,在这种情况下,这不会让人不舒服,但如果我想赋予窗体和此字段GlobalKey-在与字段的任何交互中,我看到窗体正在一次又一次地破坏和构建 Doctor summary (to see all details, run flutter

我在家里学习颤振来创建我的应用程序,面临着颤振的不可理解性;当我在导航器的任何路径的任何小部件中创建一个带有字段的表单时,我在点击formfield和关闭键盘时看到了该路径的重建。如果我移除
GlobalKey
并移除
GlobalKey
-小部件在点击并隐藏键盘时仍然重建,在这种情况下,这不会让人不舒服,但如果我想赋予窗体和此字段GlobalKey-在与字段的任何交互中,我看到窗体正在一次又一次地破坏和构建

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!
导入“包装:颤振/材料.省道”;
进口“包装:颤振_mobx/颤振_mobx.dart”;
导入“包:quich/controllers/user_controller.dart”;
导入“package:quich/route/routes.dart”;
导入“package:quich/screens/login_screen.dart”;
导入“包:quich/screens/splash_screen.dart”;
导入“package:quich/store/app_store.dart”;
void main()异步{
runApp(Quich());
等待$store.storage.ready;
var uc=UserController();
var isValid=wait uc.isTokenValid(标记:“标记”);
$store.isAuth=isValid;
$store.isLoading=false;
}
类Quich扩展StatefulWidget{
@凌驾
State createState()=>\u QuichState();
}
类_QuichState扩展状态{
最终控制器=文本编辑控制器();
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“ааааааа”,
主题:主题数据(
主样本:颜色。蓝色,
),
initialRoute:Routes.splash,
路线:{
Routes.splash:(上下文)=>Observer(生成器:(41;){
返回屏幕();
}),
Routes.login:(上下文){
打印(“超级父构建”);
返回LoginScreen();
final formKey=GlobalKey();
最终字段键=GlobalKey();
返回脚手架(
正文:专栏(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
形式(
孩子:填充(
填充:常数边集全部(15.0),
子项:TextFormField(
控制器:控制器,
钥匙:现场钥匙
),
),
key:formKey,
),
钮扣杆(
儿童:[
材料按钮(
子项:文本('ППаааааа',样式:文本样式(颜色:Colors.white)),
onPressed:()=>Navigator.of(context.pushName)(Routes.splash),
颜色:颜色。浅蓝色,
)
],
)
],
),
);
}
},
);
}
}
有什么能帮我创建一个表单,在导航器的内部有全局键的字段-我搜索了表单和导航的示例,但在导航器中找不到带有全局键的表单

UPD:看起来StackOverflow代码编辑器“eat”类型定义了一些代码部分。我附上一张带有代码的图像,请参见视频示例:

p.S.问题解决了,如果您感兴趣,可以在俄语版的“p.p.S”栏中看到该问题的解决方案:

在flatter
中,key
属性用于将小部件的现有实例与新实例进行比较,并决定下一步要做什么:创建新状态或使用现有状态、构建新子树或重用现有状态。如果没有给出一个键,颤振将使用小部件在小部件树中的位置作为键。若树结构并没有发生太多的变化,那个么若只有一个小的变化,状态树或子树就很有可能被重用

GlobalKey()
的思想是创建它的一个实例,并将其保存在应用程序树层次结构中非常高的位置

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

  • 您保留了相同的
    GlobalKey()
  • 您的小部件未完全从树中删除。若小部件被移除,它的状态和子树将消失,下次它进入应用程序的树状态时,子树将被重新创建

在代码示例中,您没有将
GlobalKey()
赋值给可重用变量。在您的例子中,
Globalkey()
的新实例是在构建函数中创建的。这将导致在每次更新时创建新的唯一密钥。新的唯一键意味着widget没有链接到widget的前一个实例,因此没有状态和子树被继承。

我注意到您在扩展类时没有使用正确的泛型方法

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<StatefulWidget> createState() => _QuichState();
}

class _QuichState extends State<Quich> {
  final controller = TextEditingController();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Регистрация',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: Routes.splash,
      routes: <String, WidgetBuilder>{
        Routes.splash: (context) => Observer(builder: (_) {
          return SplashScreen();
        }),
        Routes.login: (context) {
          print('SUPER PARENT BUILD');
          return LoginScreen();
          final formKey = GlobalKey<FormState>();
          final fieldKey = GlobalKey<FormFieldState>();
          return Scaffold(
            body: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Form(
                  child: Padding(
                    padding: const EdgeInsets.all(15.0),
                    child: TextFormField(
                      controller: controller,
                      key: fieldKey
                    ),
                  ),
                  key: formKey,
                ),
                ButtonBar(
                  children: <Widget>[
                    MaterialButton(
                      child: Text('Проверка', style: TextStyle(color: Colors.white)),
                      onPressed: () => Navigator.of(context).pushNamed(Routes.splash),
                      color: Colors.lightBlue,
                    )
                  ],
                )
              ],
            ),
          );
        }
      },
    );
  }
}
类_QuichState扩展状态{}
试试这个, 接下来,我将给您一个示例代码,以便您可以从中匹配您的代码

 class _QuichState extends State<Quich>{}
返回表单(
键:_formKey,
子:列(
crossAxisAlignment:crossAxisAlignment.start,
儿童:[
TextFormField(
验证器:(值){
if(value.isEmpty){
返回“请输入一些文本”;
}
},
),
填充物(
填充:常量边集。对称(垂直:16.0),
孩子:升起按钮(
已按下:(){
//如果表单有效,Validate将返回true;如果
//表格无效。
if(_formKey.currentState.validate()){
//如果表单有效,我们希望显示一个Snackbar
脚手架(上下文)
.showSnackBar(SnackBar(内容:文本(“处理数据”));
}
},
子项:文本('Submit'),
),
),
],
),
);
在此之后,创建一个全局键,该键将唯一标识表单小部件并允许 让我们验证表格或其他活动

注意:这是GlobalKey,不是GlobalKey

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

  final _formKey = GlobalKey<FormState>();