flutter表單Form內部實現原理淺析
使用示例
閱讀原理之前請可以先移步到: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()
進入原始碼
class Form extends StatefulWidget {
...
const Form({
Key key,
可以看到,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的方法非常清晰,遍歷FormFieldState型別的_fields集合,並逐個呼叫FormFieldState型別子元素的validate方法。從這裡可以知,FormFieldState型別的子元素,肯定跟TextFormField有關聯。
TextFormField和FormFieldState關係
看下TextFormField原始碼
class TextFormField extends FormField<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關聯
從上面分析可知,Form繼承StatefulWidget,FormState是From的State,Form一步呼叫所有關聯表單的方法validate是FormState的方法;TextFormField也是StatefulWidget型別,並且FormFieldState也是TextFormField的State;
再回頭看Form的validate最終呼叫的_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;
}
...
}
可以看到_fields資料有變化在_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);
...
}
}
從上可知:
- FormState的_register和_unregister調用出現在FormFieldState裡,並且會把FormFieldState傳給_register和_unregister;
- 在FormFieldState的build方法裡通過Form.of(context)呼叫_register將自己的FormFieldState傳給FormState並加入_fields;
- 在FormFieldState的deactivate方法裡通過Form.of(context)呼叫_unregister將自己的FormFieldState從FormState的_fields中移掉;
(未完待續。。。)
http://m.cntricycle.com/20201127/4884066.html
http://m.cntricycle.com/20201127/8628840.html
http://m.cntricycle.com/20201127/6226442.html
http://m.cntricycle.com/20201127/0660440.html
http://m.cntricycle.com/20201127/2404684.html
http://m.cntricycle.com/20201127/6824268.html
http://m.cntricycle.com/20201127/2620626.html
http://m.cntricycle.com/20201127/0640408.html
http://m.cntricycle.com/20201127/6044086.html
http://m.cntricycle.com/20201127/2868864.html
http://m.cntricycle.com/20201127/4822804.html
http://m.cntricycle.com/20201127/8224448.html
http://m.cntricycle.com/20201127/2428482.html
http://m.cntricycle.com/20201127/6048048.html
http://m.cntricycle.com/20201127/6428220.html
http://m.cntricycle.com/20201127/2426826.html
http://m.cntricycle.com/20201127/8646020.html
http://m.cntricycle.com/20201127/0406800.html
http://m.cntricycle.com/20201127/0666222.html
http://m.cntricycle.com/20201127/8680064.html
http://m.cntricycle.com/20201127/2480686.html
http://m.cntricycle.com/20201127/2246068.html
http://m.cntricycle.com/20201127/2802826.html
http://m.cntricycle.com/20201127/0420408.html
http://m.cntricycle.com/20201127/0040460.html
http://m.cntricycle.com/20201127/2640002.html
http://m.cntricycle.com/20201127/6026806.html
http://m.cntricycle.com/20201127/6228484.html
http://m.cntricycle.com/20201127/8862266.html
http://m.cntricycle.com/20201127/2600248.html