美文网首页Flutter
flutter表单Form内部实现原理浅析(一)

flutter表单Form内部实现原理浅析(一)

作者: HawkFlying | 来源:发表于2020-11-27 15:51 被阅读0次

使用示例

阅读原理之前可以先移步到:flutter 表单Form使用示例,大致了解下Form怎么使用。

实现原理分析

从上面例子可知,主要用到Form+TextFormField,那么我们就从Form+TextFormField入手来分析。

Form+TextFormField结构上的关系

代码我做了精简版,主要为了突出结构,如下:

final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  Form(
            key:_formKey,
            child:
                    ...
                    TextFormField( 
                        validator: (value) {
                              ...
                              return xxx; 
                        },
                    )
                    ...
                    TextFormField( 
                        validator: (value) {
                              ...
                              return xxx; 
                        },
                    )
                    ...

从上面可以知道,Form是容器,将所有关联的TextFormField装在里面,也就是说Form和所有关联的TextFormField在同一棵树结构上,Form节点是所有关联TextFormField的父节点,先记住这个结论。

Form如何一步校验所有关联的TextFormField

Form validate方法内部实现

之前使用Form一步校验所有表单时,就比较好奇Form是怎么和TextFormField产生关联的,就想看看它是怎么实现的。Form一步校验所有表单的方法是调用如下:

_formKey.currentState.validate()

进入Form源码

class Form extends StatefulWidget {
  ...
  const Form({
    Key key,
    @required this.child,
    this.autovalidate = false,
    this.onWillPop,
    this.onChanged,
  })
  ...
}
class FormState extends State<Form> {
  int _generation = 0;
  final Set<FormFieldState<dynamic>> _fields = <FormFieldState<dynamic>>{};
  ...
  void _forceRebuild() {
    setState(() {
      ++_generation;
    });
  }

  bool validate() {
    _forceRebuild();
    return _validate();
  }

  bool _validate() {
    bool hasError = false;
    for (FormFieldState<dynamic> field in _fields)
      hasError = !field.validate() || hasError;
    return !hasError;
  }
  ...
}

可以看到,Form继承StatefulWidget,Form一步调用所有关联表单的方法validate是FormState的方法,validate方法里最终调用_validate方法

 bool _validate() {
    bool hasError = false;
    for (FormFieldState<dynamic> field in _fields)
      hasError = !field.validate() || hasError;
    return !hasError;
  }

_validate里实现逻辑比较清晰:

  • _fields:FormFieldState类型的集合
  • field.validate():调用FormFieldState类型元素的validate方法
  • !field.validate() || hasError:只要有一个field.validate() 返回false,hasError值就为true(||或运算:两个变量参与||运算时,当两个变量有一个为true时,结果即为true,只有当两个变量均为false时结果为false)
  • 翻译过来就是:遍历FormFieldState类型的集合_fields,并逐个调用FormFieldState类型子元素的validate方法,当有一个FormFieldState类型子元素的validate方法返回false时(注:这里是全部FormFieldState类型子元素都会调用validate),_validate就返回false,FormState的validate方法也返回false,也就是Form中有校验不合格的表单。从这里可以知,FormFieldState类型的子元素,肯定跟TextFormField有关联。

TextFormField和FormFieldState关系

看下TextFormField源码

class TextFormField extends FormField<String> {
...
 @override
  _TextFormFieldState createState() => _TextFormFieldState();
}
class _TextFormFieldState extends FormFieldState<String> {
...
}

可以看到TextFormField继承FormField,并且返回一个FormFieldState类型的State,这结构跟StatefulWidget类似;
再看下FormField源码

class FormField<T> extends StatefulWidget {
   ...
  @override
  FormFieldState<T> createState() => FormFieldState<T>();
}

class FormFieldState<T> extends State<FormField<T>> {
 ...
}

由此可知,FormField继承StatefulWidget,FormFieldState为FormField的State,所以TextFormField也是StatefulWidget类型,并且FormFieldState也是TextFormField的State。

Form和TextFormField关联

从上面分析可知:
(1)、Form继承StatefulWidget,FormState是From的State,Form一步校验所有关联表单的方法最终调用的是FormState的validate方法;
(2)、FormState的validate方法:遍历FormFieldState类型的集合,并逐个调用FormFieldState类型子元素的validate方法,当有一个FormFieldState类型子元素的validate方法返回false时,FormState的validate方法也返回false,表示Form中有校验不合格的表单;
(3)、TextFormField也是StatefulWidget类型,并且FormFieldState是TextFormField的State;
再回头看Form的validate方法,最终调用的FormState的_validate方法:

class FormState extends State<Form> {

  final Set<FormFieldState<dynamic>> _fields = <FormFieldState<dynamic>>{};
  ...
  bool _validate() {
    bool hasError = false;
    for (FormFieldState<dynamic> field in _fields)
      hasError = !field.validate() || hasError;
    return !hasError;
  }
  ...
}

_validate主要实现遍历FormFieldState类型的集合_fields,并逐个调用FormFieldState类型子元素的validate方法。
这里FormFieldState类型的_fields集合数据从哪里来呢?

class FormState extends State<Form> {
 ...
 final Set<FormFieldState<dynamic>> _fields = <FormFieldState<dynamic>>{};
 void _register(FormFieldState<dynamic> field) {
    _fields.add(field);
  }

  void _unregister(FormFieldState<dynamic> field) {
    _fields.remove(field);
  }
  ...
  bool _validate() {
    bool hasError = false;
    for (FormFieldState<dynamic> field in _fields)
      hasError = !field.validate() || hasError;
    return !hasError;
  }
  ...
}

可以看到FormFieldState类型的集合_fields的数据变化是在_register和_unregister方法调用的时侯,这样我们只需要找到FormState的_register和_unregister方法在哪调用就可以知道FormFieldState类型的集合从哪里来了。
FormState的_register和_unregister方法调用地方:

class FormFieldState<T> extends State<FormField<T>> {
  ...
  @override
  void deactivate() {
    Form.of(context)?._unregister(this);
    super.deactivate();
  }

  @override
  Widget build(BuildContext context) {
    ...
    Form.of(context)?._register(this);
    ...
  }

  bool validate() {
    ...
  }


}

从上可知:

  • FormState的_register和_unregister调用出现在FormFieldState里,并会把自己传给_register和_unregister;
  • 在FormFieldState的build方法中,通过Form.of(context)调用_register将自己传给FormState,并加入_fields集合;
  • 在FormFieldState的deactivate方法中,通过Form.of(context)调用_unregister将自己传给FormState,并从_fields集合中移掉;

由于FormFieldState是TextFormField的State,FormState是From的State,FormFieldState通过Form.of(context)将自己传给FormState,FormState保存FormFieldState的集合,这样FormState就可以调用就FormFieldState的方法了,Form也就和TextFormField关联起来了。

相关文章

网友评论

    本文标题:flutter表单Form内部实现原理浅析(一)

    本文链接:https://www.haomeiwen.com/subject/onuziktx.html