The role of GlobalKey
Let’s talk about the conclusion first, and the origin of this conclusion will be analyzed later: Each Widget
corresponds to one Element
, we can directly Widget
operate on it, but we cannot directly operate Widget
the corresponding one Element
. It's the key GlobalKey
to direct access Element
. Through GlobalKey
can get the Widget
corresponding Element
, such as get StatelessElement
and StatefulElement
. For example, if it is obtained StatefullElement
, then we can get StatefulElement
the State
object.
Let's take the Form
form as an example to analyze GlobalKey
why Widget
the corresponding one can be obtained Element
.
GlobalKey Practical Example
There must be an input box for entering the user name and password for login, Flutter
and we only implement it in the form of Form
form + TextFormField
. Now let 's talk about the simple use of Form
sum . The login interface in the demo is as follows:TextFormField
Then we click the submit button without entering any characters, the effect is as follows:
The code for the above layout is as follows:
import 'package:flutter/material.dart';
//使用GlobalKey来使用Form
class FormUseGlobalKeyDemo extends StatefulWidget {
@override
_FormState createState() {
return _FormState();
}
}
class _FormState extends State<FormUseGlobalKeyDemo> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("使用GlobalKey的Form表单"),
),
body: _createForm(),
);
}
final _formKey = GlobalKey<FormState>();
Widget _createForm() {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
validator: (value) {///输入字符校验
if (value.isEmpty) {
return '请输入文字';
}
return null;
},
),
_createSubmitButton(),///创建submit按钮
],
),
);
}
Widget _createSubmitButton() {
return RaisedButton(
onPressed: () {
Form.of(context);
if (_formKey.currentState.validate()) {///点击时开始非空验证
print('验证通过');
}
},
child: Text('Submit'),
);
}
}
GlobalKey
First initialize the object as shown above . Then set this object as Form
the key, and finally click the Submit button, we do not directly operate TextFormField
, but through the non-empty verification of the content _formKey.currentState.validate
of the input box . Its type TextFormField
in the code is :_formKey.currentState
FormState
class Form extends StatefulWidget {
const Form({
Key key,
@required this.child,
}) ;
@override
FormState createState() => FormState();
//调用Form.of(context)也可以获取FormState对象
//详情请看【Flutter之实战InheritedWidget详解】
static FormState of(BuildContext context) {
final _FormScope scope = context.inheritFromWidgetOfExactType(_FormScope);
return scope?._formState;
}
}
The principle of GlobalKey to obtain Element
abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {
//一个静态的变量map集合
static final Map<GlobalKey, Element> _registry = <GlobalKey, Element>{};
}
As can be seen from GlobalKey<T extends State<StatefulWidget>>
the class structure of , it GlobalKey
is mainly used to store state information State<StatefulWidget>
, State
which refers to StatefulWidget
the state class, which is created by StatefulWidget
the createState
method:
abstract class StatefulWidget extends Widget {
//Key是个options的,可以设置也可以不设置
const StatefulWidget({ Key key }) : super(key: key);
@protected
State createState();
}
Why GlobalKey.currentState
can you get it through the above FormState
? How are the two related? Find out now.
Let's take a look at the specific implementation GlobalKey
of the method:currentState
T get currentState {
//当前的Element对象
final Element element = _currentElement;
//检测是否是SatefulElement对象
if (element is StatefulElement) {
final StatefulElement statefulElement = element;
//获取StatefulElement对象的State对象
final State state = statefulElement.state;
//如果状态匹配,则返回对应的T
if (state is T)
return state;
}
return null;
}
//_currentElement是一个map集合Map<GlobalKey, Element>
//该集合以GlobalKeyweight对象,其值保存的是Element。
Element get _currentElement => _registry[this];
There GlobalKey
is a static _registry Map
collection inside, which is regarded GlobalKey
as key and Element
value; the currentState
method provided is to use the GlobalKey
object as Key
the corresponding StatefulElement
object, and then StatefulElement.state
obtain the specific value from it FormState
, then when to fill the _registry collection with data Woolen cloth? Through the analysis of the correspondence between Fultter's Element and Widget, we know that a method Element
will be called after creation mount
:
void mount(Element parent, dynamic newSlot) {
///省略部分代码
if (widget.key is GlobalKey) {
final GlobalKey key = widget.key;
//将Element对象注册进来
key._register(this);
}
}
//GlobalKey的_register方法。
void _register(Element element) {
_registry[this] = element;
}
It can be found that the mount method Element
injects GlobalKey
the static map collection we created into! So GlobalKey
the effect is: * Holds the current object, so the current Widget
one can be obtained through the object, and the related methods of manipulation by obtaining the state object . For example , the validate() method performs a non-null checkElement
GlobalKey
StatefulWidget
StatefullElement
StatefullElement
State
State
FormState
.
In fact, we can also use the Form.of(context)
method to obtain the FormState
object, and then call the validate method to complete TextFormField
the non-empty check. For the principle, see the detailed analysis of Flutter's actual combat InheritedWidget
Full code: https://github.com/guoyanqiu/flutter_login