Flutter之GlobalKey详解
在正式开始阅读本文之前,希望读者阅读下博主的Flutter之BuilderContext和Widget关系浅析和Fultter之Element和Widget对应关系这两篇博文,这是本篇博文的理论知识储备。通过这两篇博文你可以了解到:
1、Widget和Element的对应关系
2、Widget和Element的初始化时机
3、Flutter的BuildContext到底是什么玩意
4、StatefulWidget的state跟StatefulElement之间的联系
本文的的涉及到的代码demo,点此查看
GlobalKey详解
- GlobalKey的作用
- GlobalKey实战举例
- GlobalKey获取Element的原理
GlobalKey的作用
先说结论,后文会分析此结论的由来: 每个Widget
都对应一个Element
,我们可以直接对Widget
进行操作,但是无法直接操作Widget
对应的Element
。而GlobalKey
就是那把直接访问Element
的钥匙。通过GlobalKey
可以获取到Widget
对应的Element
,比如获取StatelessElement
和StatefulElement
. 比如如果获取到了StatefullElement
,那么我们就可以获取StatefulElement
的State
对象。
下面我们就以Form
表单为例来分析GlobalKey
为什么可以获取Widget
对应的Element
。
GlobalKey实战举例
登录肯定要有输入用户名和密码的输入框,在Flutter
中我们只用Form
表单+TextFormField
的形式加以实现。现在就来讲讲Form
和TextFormField
的简单使用,demo中登录界面如下:
然后我们在不输入任何字符的情况下点击submit按钮,效果如下所示:
上图布局的代码如下所示:
如上所示首先初始化GlobalKey
对象。然后将此对象设置为Form
的key,最后再点击Submit按钮的时候,我们没有直接操作TextFormField
,而是通过_formKey.currentState.validate
对输入框TextFormField
的内容进行非空验证。代码中的_formKey.currentState
其类型是FormState
:
class Form extends StatefulWidget {const Form({Key key,@required this.child,}) ;@overrideFormState createState() => FormState();//调用Form.of(context)也可以获取FormState对象//详情请看【Flutter之实战InheritedWidget详解】static FormState of(BuildContext context) {final _FormScope scope = context.inheritFromWidgetOfExactType(_FormScope);return scope?._formState;}}
GlobalKey获取Element的原理
abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {//一个静态的变量map集合static final Map<GlobalKey, Element> _registry = <GlobalKey, Element>{};
}
,从 GlobalKey<T extends State<StatefulWidget>>
的类结构可以看出,GlobalKey
主要用来存储状态信息 State<StatefulWidget>
,State
指的是StatefulWidget
的状态类,通过StatefulWidget
的createState
方法创建:
abstract class StatefulWidget extends Widget {//Key是个options的,可以设置也可以不设置const StatefulWidget({ Key key }) : super(key: key);@protectedState createState();
}
上文中为什么通过GlobalKey.currentState
就可以获取到FormState
呢?二者是怎么关联起来的呢?现在就来一探究竟。
先来看看GlobalKey
的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;//如果状态匹配,则返回对应的Tif (state is T)return state;}return null;}//_currentElement是一个map集合Map<GlobalKey, Element> //该集合以GlobalKeyweight对象,其值保存的是Element。Element get _currentElement => _registry[this];
在GlobalKey
内部有一个静态的的_registry Map
集合,该集合以GlobalKey
为key,以Element
为value;其提供的currentState
方法就是以GlobalKey
对象为Key
获取对应的StatefulElement
对象,然后从StatefulElement.state
里获取具体的值FormState
,那么什么时候往_registry 集合里填充数据呢?通过Fultter之Element和Widget对应关系解析我们知道一个Element
在创建之后会调用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;}
可以发现在mount方法将我们创建的Element
注入到GlobalKey
的静态map集合中去!所以GlobalKey
的作用就是:*持有当前Widget
的Element
对象,因此通过GlobalKey
对象可以获取到当前StatefulWidget
的StatefullElement
,在通过StatefullElement
获取State
状态对象,从而操控State
的相关方法。比如FormState
的validate()方法进行非空校验。
事实上我们还可以使用Form.of(context)
方法也可以获到FormState
对象,然后调用validate方法完成TextFormField
的非空校验,其中原理,详细解析见Flutter之实战InheritedWidget详解
本篇博文更新于2021年12月7号。
Flutter之GlobalKey详解相关推荐
- 导出jar插件_Fluttify输出的Flutter插件工程详解
系列文章: yohom:Fluttify输出的Flutter插件工程详解zhuanlan.zhihu.com yohom:开发Flutter插件必备原生SDK->Dart接口生成引擎`Flut ...
- flutter 生命周期详解
flutter 生命周期详解 简介 一.widget 生命周期 二.APP 生命周期 总结 简介 众所周知,程序是有生命周期的,那么flutter 的生命周期是什么呢? flutter 的生命周期大体 ...
- Flutter - 底部导航详解与案例示范
Flutter - 底部导航栏解析与示范 作者: jcLee95 邮箱 :291148484@163.com CSDN 主页:https://blog.csdn.net/qq_28550263?spm ...
- Flutter - fast_mvvm 作者详解
Flutter fast_mvvm 使用帮助 fast_mvvm 创作思路 Demo 讲解 UserModel 初始化 ArticleEntity ArticleVM ArticlePage View ...
- Flutter Text 参数详解
1.继承关系 Object > Diagnosticable > DiagnosticableTree > Widget > StatelessWidget > Text ...
- Flutter Container 参数详解
1 基本内容 1.1 继续关系 Object > Diagnosticable > DiagnosticableTree > Widget > StatelessWidget ...
- Flutter Scaffold 参数详解
1.Scaffold 1.1 继承关系 Object > Diagnosticable > DiagnosticableTree > Widget > StatefulWidg ...
- Flutter BlendMode混合模式详解
原文: https://docs.flutter.io/flutter/dart-ui/BlendMode-class.html 1.介绍: 在画布上绘画时使用的算法. 在画布上绘制形状或图像时,可以 ...
- 一起看 I/O | Flutter 3 更新详解
作者 / Kevin Jamaul Chisholm, Technical Program Manager for Dart and Flutter at Google 又到了 Flutter 稳定版 ...
- Flutter 多渠道打包详解(埋点统计系列文章)
我是 Zero,废话不多说,脑图奉上 脑图梳理 只要你关注 Flutter,这篇文章你绝对用得着 ==> 强烈建议➕收藏 多渠道打包介绍 多渠道打包的主要作用是满足产品的运营需求,统计渠道和活动 ...
最新文章
- 对于正交频分复用的异构网络的理解
- IE8经常停止工作和显示异常
- 3.Linux文件与目录管理
- 一文了解Spring Cloud Stream体系
- Maven拉取私服Jar包和发布jar包到maven私服
- mac ssh客户端_Electerm for Mac(ssh客户端)
- C++函数内部实现的规则
- World Currency Symbols世界货币符号
- inttypes.h源码,VS编译需要
- pywinauto实战-操作h2testw.exe自动化测试脚本
- 协议 ---ISO/OSI协议模型详解
- c语言小车程序,51单片机控制小车运动C语言代码
- 工业元宇宙的价值和发展
- 方舟手游修改服务器难度,方舟手游中途可以修改难度吗
- php中如何过滤关键字,PHP - 过滤关键字
- 【WPS】WPS之如何给文件加密?
- 【HTML学习笔记】link标签中的href路径
- Android实现身份证识别
- MySQL 查询练习(1)
- 服务器安全狗拦截微信,服务器软件安全狗误拦截百度蜘蛛
热门文章
- hashmap扩容_我说我了解集合类,面试官竟然问我为啥HashMap的负载因子不设置成1!?
- adb echo shell 覆盖_Shell脚本的应用(一)
- vbs比较两个数组里的数的大小_BAT 高频面试题:寻找两个有序数组的中位数
- Java进阶:SpringMVC中放行静态资源
- Java进阶: springmvc已经引入jar包仍报错lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper
- Python:字符串、列表、元组、字典之间的相互转换
- jq移除一条html语句,jquery html()删除脚本标签
- 关于线程协同的火车票售卖程序
- 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
- 关于new FormData() 对象的用法