前言

Everything’s a widget!

Widget

Flutter 中 Widget是一个“描述一个UI元素的配置信息”,Widget就是接受元素,而不是真是绘制的显示元素。
类比原生的Android开发,Widget更像是负责UI配置的xml文件,而非负责绘制组件的View。 当一个Widget状态发生变化时,Widget就会重新调用build()函数来返回控件的描述,过程中Flutter框架会与之前的Widget进行比较,确保实现渲染树中最小的变动来保证性能和稳定性。换句话说,当Widget发生改变时,渲染树只会更新其中的一小部分而非全部重新渲染。

源码

@immutable
abstract class Widget extends DiagnosticableTree {const Widget({ this.key });final Key? key;@protected@factoryElement createElement();@overrideString toStringShort() {final String type = objectRuntimeType(this, 'Widget');return key == null ? type : '$type-$key';}@overridevoid debugFillProperties(DiagnosticPropertiesBuilder properties) {super.debugFillProperties(properties);properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;}@override@nonVirtualbool operator ==(Object other) => super == other;@override@nonVirtualint get hashCode => super.hashCode;static bool canUpdate(Widget oldWidget, Widget newWidget) {return oldWidget.runtimeType == newWidget.runtimeType&& oldWidget.key == newWidget.key;}...
}

图:

@immutable

@immutable widget中的属性时不可变的,如果有可变的你需要放在state中。

如果属性发生变更flutter则会重新构建Widget树,一旦 Widget 自己的属性变了自己就会被替换。
如你在开发过程中会有如下提示:This class (or a class that this class inherits from) is marked as ‘@immutable’, but one or more of its instance fields aren’t final:

key

主要用于控制当 Widget 更新时,对应的 Element 如何处理 (是更新还是新建)。若某 Widget 是其「Parent Widget」唯一的子节点时,一般不用设置 key

LocalKey

LocalKey是diff算法的核心所在,用做Element和Widget的比较。常用子类有以下几个:

ValueKey:以一个数据为作为key,比如数字、字符等。
ObjectKey:以Object对象作为Key。
UniqueKey:可以保证key的唯一性,如果使用这个类型的key,那么Element对象将不会被复用。
PageStorageKey:用于存储页面滚动位置的key。

GlobalKey

每个globalkey都是一个在整个应用内唯一的key。globalkey相对而言是比较昂贵的,如果你并不需要globalkey的某些特性,那么可以考虑使用Key、ValueKey、ObjectKey或UniqueKey。
他有两个用途:

  1. 允许widget在应用程序中的任何位置更改其parent而不丢失其状态。应用场景:在两个不同的屏幕上显示相同的widget,并保持状态相同。
  2. 可以获取对应Widget的state对象:

createElement

一个 widget 可以对应多个Element

canUpdate

控制一个widget如何替换树中另一个widget。如果两个widget的runtimeType与key相同,则表示新的widget将替换旧的widget,并调用Element.update更新Element;否则旧的element将从树中移出,新的element插入树中。

Widget在重新build的时候,是增量更新的,而不是全部更新
runtimeType就是这个widget的类型

Widget类大家族

简述(后面文章将展开讲解):

  • StatelessWidget:无状态Widget
  • StatefulWidget:有状态Widget,值得注意的是StatefulWidget是不可变的,变化的状态在。
  • ProxyWidget:其有2个比较重要的子类, ParentDataWidget和InheritedWidget
  • RenderObjectWidget:持有RenderObject对象的Widget,RenderObject是完成界面的布局、测量与绘制,像Padding,Table,Align都是它的子类

Widget的创建可以做到复用,通过const修饰,否则setState后,Widget重新被创建了(Element不会重建)

Element

通过Widget Tree,会生成一系列Element Tree,其主要功能如下:

  1. 维护这棵Element Tree,根据Widget Tree的变化来更新Element Tree,包括:节点的插入、更新、删除、移动等
  2. Element 是 Widget 和 RenderObject 的粘合剂,根据 Element 树生成 Render 树(渲染树)

Element类大家族

两大类:

简述(后面文章将展开讲解):

ComponentElement

组合类Element。这类Element主要用来组合其他更基础的Element,得到功能更加复杂的Element。开发时常用到的StatelessWidget和StatefulWidget相对应的Element:StatelessElement和StatefulElement,即属于ComponentElement。

RenderObjectElement

渲染类Element,对应Renderer Widget,是框架最核心的Element。RenderObjectElement主要包括LeafRenderObjectElement,SingleChildRenderObjectElement,和MultiChildRenderObjectElement。其中,LeafRenderObjectElement对应的Widget是LeafRenderObjectWidget,没有子节点;SingleChildRenderObjectElement对应的Widget是SingleChildRenderObjectWidget,有一个子节点;MultiChildRenderObjectElement对应的Widget是MultiChildRenderObjecWidget,有多个子节点。

Element生命周期

Element有4种状态:initial,active,inactive,defunct。其对应的意义如下:

  • initial:初始状态,Element刚创建时就是该状态。
  • active:激活状态。此时Element的Parent已经通过mount将该Element插入Element Tree的指定的插槽处(Slot),Element此时随时可能显示在屏幕上。
  • inactive:未激活状态。当Widget Tree发生变化,Element对应的Widget发生变化,同时由于新旧Widget的Key或者的RunTimeType不匹配等原因导致该Element也被移除,因此该Element的状态变为未激活状态,被从屏幕上移除。并将该Element从Element Tree中移除,如果该Element有对应的RenderObject,还会将对应的RenderObject从Render Tree移除。但是,此Element还是有被复用的机会,例如通过GlobalKey进行复用。
  • defunct:失效状态。如果一个处于未激活状态的Element在当前帧动画结束时还是未被复用,此时会调用该Element的unmount函数,将Element的状态改为defunct,并对其中的资源进行清理。

Element4种状态间的转换关系如下图所示:

跟我学flutter:细细品Widget(一)WidgetElement初识相关推荐

  1. 学 Flutter 不理解 Widget/Element/Render 三棵树?啥也不是!

    一.导语 Hi,大家好,这里是承香墨影! Flutter 是 Google 发布的跨平台 UI 框架,而其中与 UI 相关的,最重要的就是 Widget & Element & Ren ...

  2. Flutter学习-基础Widget

    Flutter学习-基础Widget 1. Flutter编程范式 1.1 编程范式的理解 1.2 flutter的编程范式 2. Text Widget 2.1 普通文本展示 2.2 富文本 2.3 ...

  3. Flutter一切皆widget但是不要将所有东西放入一个widget

    本文主要介绍Flutter一切皆widget但是不要将所有东西放入一个widget 作为 Flutter 开发人员,我相信您在您的开发生活中至少听说过这句流行的句子:"**一切都是widge ...

  4. Flutter之基础Widget

    原文博客地址: Flutter之基础Widget Flutter和Dart系列文章 项目GitHub地址 Flutter作为一种全新的响应式,跨平台,高性能, 完全免费.开源的移动开发框架 Widge ...

  5. 计算机科学的中心舞台在于,【名师】上海财经大学教授陆品燕:以赤子之心长者之智,打造国际一流理论计算机科学研究中心...

    从超级学霸到世界知名理论计算机科学家,陆品燕致力于扎根中国大地打造国际一流理论计算机科研中心,为国家培养大量国际化人才. 名师聚焦 陆品燕:上海财经大学信息管理与工程学院教授.副院长,理论计算机科学研 ...

  6. 给Flutter中的Widget设置透明度

    给Flutter中的Widget设置透明度 在项目开发中,需要经常用到透明度:比如在app中弹出一个提示框,这个时候的提示框就需要上下左右离边距有一定的距离,然后背景色舍黑色,需要设置透明度为0.4: ...

  7. Flutter如何使widget始终保持在屏幕底部

    Flutter如何使widget始终保持在屏幕底部 问题描述 在登录或者注册页面,需要在底部展示一些隐私政策或者是隐私协议,就是用了一种Stack布局方式,但是使用这种方式在没有键盘弹出的时候看起来一 ...

  8. Flutter基础-(3)Widget之文本Text

    本来打算第三篇文章来讲解 Flutter 单子布局widget , 奈何 18种单子布局widget 内容颇多,加之年后有了新项目要开发 , 使得文章产出周期被拉长 :( . 这里先来篇简单的关于Te ...

  9. 跟李宁老师学Python视频教程(1):初识Python-李宁-专题视频课程

    跟李宁老师学Python视频教程(1):初识Python-1142人已学习 课程介绍         本系列课程一共20套,每一套视频课程会深入讲解Python的一类知识点.Python是当今炙手可热 ...

最新文章

  1. 厉害了,在Pandas中用SQL来查询数据,效率超高
  2. 2.vue的diff算法(2020.12.07)
  3. Java的四种包访问权限
  4. 会c语言如何快速入门python,初学者如何从C语言到Python的转化(北大陈斌老师的举例 )...
  5. WinDirStat 电脑C盘分析神器
  6. mac 用 VMware Fusion 安装 ubuntu
  7. 读取视频并将视频转换成图片
  8. 微积分基本公式-牛顿莱布尼兹公式
  9. 正则十八式-第三式:龙跃于渊
  10. 机器学习-GB、GBDT、XGboost、Adaboost
  11. 移动开发平台WorkPlus | 快速实现企业移动应用集成化
  12. 如何写一个proto消息
  13. Java学习(84)Java集合——案例:公告管理(ArrayList增删改查)
  14. 微型公司小团队对软件项目开发管理和规范化的思考
  15. [机器学习基础][台大林轩田]机器学习概念
  16. AppIcon和LaunchImage尺寸
  17. STM32开发实战:W25Q32JV SPI Flash详解
  18. 无人驾驶数据库汇总(不断更新)
  19. 《iOS用户体验》总结与思考-改动版
  20. 那些年啊,那些事——一个程序员的奋斗史 ——53

热门文章

  1. DS1302可调时钟
  2. 【马红“名师+”研修共同体】师徒结对传帮带,青蓝同心共成长
  3. windows中的guest与everyone用户的作用
  4. Win10设置java环境变量
  5. Centos7+puppet+foreman,实现部署OS
  6. 中国人工智能企业CIMCAI全球港航人工智能领军企业,成熟智慧港航产品行业顶尖,智慧港航智能港口数字化港口自动化中国人工智能企业
  7. Hadoop集群搭建配置教程
  8. iOS开发——项目中的地图跳转(苹果地图,百度地图,高德地图)
  9. 习惯---哈佛大学推荐20个快乐的习惯
  10. 输入8-16位数字和字母组成的密码