在正式开始阅读本文之前,希望读者阅读下博主的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,比如获取StatelessElementStatefulElement. 比如如果获取到了StatefullElement,那么我们就可以获取StatefulElementState对象。
下面我们就以Form表单为例来分析GlobalKey为什么可以获取Widget对应的Element

GlobalKey实战举例

登录肯定要有输入用户名和密码的输入框,在Flutter中我们只用Form表单+TextFormField的形式加以实现。现在就来讲讲FormTextFormField的简单使用,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 的状态类,通过StatefulWidgetcreateState方法创建:

abstract class StatefulWidget extends Widget {//Key是个options的,可以设置也可以不设置const StatefulWidget({ Key key }) : super(key: key);@protectedState createState();
}

上文中为什么通过GlobalKey.currentState就可以获取到FormState呢?二者是怎么关联起来的呢?现在就来一探究竟。

先来看看GlobalKeycurrentState方法的具体实现:

  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的作用就是:*持有当前WidgetElement对象,因此通过GlobalKey对象可以获取到当前StatefulWidgetStatefullElement,在通过StatefullElement获取State状态对象,从而操控State的相关方法。比如FormState的validate()方法进行非空校验

事实上我们还可以使用Form.of(context)方法也可以获到FormState对象,然后调用validate方法完成TextFormField的非空校验,其中原理,详细解析见Flutter之实战InheritedWidget详解

本篇博文更新于2021年12月7号。

Flutter之GlobalKey详解相关推荐

  1. 导出jar插件_Fluttify输出的Flutter插件工程详解

    系列文章: yohom:Fluttify输出的Flutter插件工程详解​zhuanlan.zhihu.com yohom:开发Flutter插件必备原生SDK->Dart接口生成引擎`Flut ...

  2. flutter 生命周期详解

    flutter 生命周期详解 简介 一.widget 生命周期 二.APP 生命周期 总结 简介 众所周知,程序是有生命周期的,那么flutter 的生命周期是什么呢? flutter 的生命周期大体 ...

  3. Flutter - 底部导航详解与案例示范

    Flutter - 底部导航栏解析与示范 作者: jcLee95 邮箱 :291148484@163.com CSDN 主页:https://blog.csdn.net/qq_28550263?spm ...

  4. Flutter - fast_mvvm 作者详解

    Flutter fast_mvvm 使用帮助 fast_mvvm 创作思路 Demo 讲解 UserModel 初始化 ArticleEntity ArticleVM ArticlePage View ...

  5. Flutter Text 参数详解

    1.继承关系 Object > Diagnosticable > DiagnosticableTree > Widget > StatelessWidget > Text ...

  6. Flutter Container 参数详解

    1 基本内容 1.1 继续关系 Object > Diagnosticable > DiagnosticableTree > Widget > StatelessWidget ...

  7. Flutter Scaffold 参数详解

    1.Scaffold 1.1 继承关系 Object > Diagnosticable > DiagnosticableTree > Widget > StatefulWidg ...

  8. Flutter BlendMode混合模式详解

    原文: https://docs.flutter.io/flutter/dart-ui/BlendMode-class.html 1.介绍: 在画布上绘画时使用的算法. 在画布上绘制形状或图像时,可以 ...

  9. 一起看 I/O | Flutter 3 更新详解

    作者 / Kevin Jamaul Chisholm, Technical Program Manager for Dart and Flutter at Google 又到了 Flutter 稳定版 ...

  10. Flutter 多渠道打包详解(埋点统计系列文章)

    我是 Zero,废话不多说,脑图奉上 脑图梳理 只要你关注 Flutter,这篇文章你绝对用得着 ==> 强烈建议➕收藏 多渠道打包介绍 多渠道打包的主要作用是满足产品的运营需求,统计渠道和活动 ...

最新文章

  1. 对于正交频分复用的异构网络的理解
  2. IE8经常停止工作和显示异常
  3. 3.Linux文件与目录管理
  4. 一文了解Spring Cloud Stream体系
  5. Maven拉取私服Jar包和发布jar包到maven私服
  6. mac ssh客户端_Electerm for Mac(ssh客户端)
  7. C++函数内部实现的规则
  8. World Currency Symbols世界货币符号
  9. inttypes.h源码,VS编译需要
  10. pywinauto实战-操作h2testw.exe自动化测试脚本
  11. 协议 ---ISO/OSI协议模型详解
  12. c语言小车程序,51单片机控制小车运动C语言代码
  13. 工业元宇宙的价值和发展
  14. 方舟手游修改服务器难度,方舟手游中途可以修改难度吗
  15. php中如何过滤关键字,PHP - 过滤关键字
  16. 【WPS】WPS之如何给文件加密?
  17. 【HTML学习笔记】link标签中的href路径
  18. Android实现身份证识别
  19. MySQL 查询练习(1)
  20. 服务器安全狗拦截微信,服务器软件安全狗误拦截百度蜘蛛

热门文章

  1. hashmap扩容_我说我了解集合类,面试官竟然问我为啥HashMap的负载因子不设置成1!?
  2. adb echo shell 覆盖_Shell脚本的应用(一)
  3. vbs比较两个数组里的数的大小_BAT 高频面试题:寻找两个有序数组的中位数
  4. Java进阶:SpringMVC中放行静态资源
  5. Java进阶: springmvc已经引入jar包仍报错lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper
  6. Python:字符串、列表、元组、字典之间的相互转换
  7. jq移除一条html语句,jquery html()删除脚本标签
  8. 关于线程协同的火车票售卖程序
  9. 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
  10. 关于new FormData() 对象的用法