当前位置: 首页 > news >正文

Flutter中的Tree

一、Widget

组合类(Composite Widgets)

如Container、Scaffold、MaterialApp等,以及通过继承StatelessWidget和StatefulWidget的类。

代理类(Proxy Widgets)

如InheritedWidget,这是一种功能型组件,可以高效快捷地实现共享数据的跨组件传递;
InheritedWidget是一个代理类Widget,主要用于在Descendant Widgets之间传递共享信息;
通过使用InheritedWidget,可以在树结构中传递信息,当子类状态变更时,可以通知父类进行对应的变更;
ParentDataWidget主要用于配置Descendant Renderer Widget的布局信息;
与InheritedWidget的作用方向相反,ParentDataWidget为具有多个子类的RenderObjectWidget提供对应的配置等,例如Stack使用已定位好的父类Widget来定位每个子Widget。

绘制类(Render Object Widgets)

这类Widget几乎涵盖了屏幕上看到的所有UI,都是通过继承RenderObjectWidget实现的;
根据对应的Element,可以分为MultiChildRenderObjectWidget、SingleChildRenderObjectWidget和LeafRenderObjectWidget,其中LeafRenderObjectWidget是那些没有子节点的Widget。

StatefulWidget生命周期

可以分为三个阶段:创建、更新和销毁;
在创建阶段中,Widget会触发一系列生命周期方法来响应不同的事件;
这些方法包括createState、initState、didChangeDependencies和build;
createState方法会在Widget被创建时调用,用于创建一个新的State对象;
initState方法会在State对象被创建后调用,用于初始化State对象。didChangeDependencies方法会在State对象依赖的对象发生变化时调用,例如父Widget发生变化时;
build方法会在创建阶段和更新阶段都会被调用,用于构建UI界面;

在更新阶段中,Widget会触发一系列生命周期方法来响应不同的事件;
这些方法包括didUpdateWidget和setState;
didUpdateWidget方法会在Widget属性发生变化时调用,例如父Widget的属性发生变化时;
setState方法会在State对象的状态发生变化时调用,用于更新状态;

在销毁阶段中,Widget会触发一系列生命周期方法来响应不同的事件;
这些方法包括deactivate和dispose;
deactivate方法会在State对象暂时从视图树中移除时调用,例如当页面被覆盖时;
dispose方法会在永久从视图树中移除时调用,通常用于释放所有资源。

Widget的更新条件

setState()方法被调用、依赖的变量或数据发生变化、parent widget发生变化、Widget Tree重建等;
总的来说就是Flutter会递归遍历新旧Widget Tree的节点,对比它们的runtimeType和key属性是否相同,如果相同就会认为不需要更新。

Key

Key共分为LocalKey和GlobalKey,通过比较hashCode来判断两个Key是否相等,在使用中需要注意Key的唯一性;
GlobalKey是一个全局唯一的Key,可以在整个应用中引用;
LocalKey直接继承至Key,它应用于拥有相同父Element的Widget进行比较的情况;
LocalKey包括ValueKey(最常用的Key类型,它将一个值赋予给Key)、ObjectKey(与ValueKey类似,但是ObjectKey使用的是对象的引用)、UniqueKey(每次创建都会生成一个唯一的Key);
PageStorageKey继承自ValueKey,是用于存储用户滚动位置的专用key,以便应用可以保留当前的滚动位置,供后续使用。

二、Element、RenderObject、Paint

从Tree到渲染

对于一个StatefulWidget,当StatefulWidget被插入到Widget Tree中时,Flutter框架会调用其createElement()方法;
createElement()方法返回一个StatefulElement实例,StatefulElement随后被挂载到Element Tree上;

StatefulElement通过调用StatefulWidget的createState()方法来创建一个状态对象(State);
这个状态对象负责管理StatefulWidget的状态,并可以在状态变化时触发重建;

在适当的时机(如widget首次构建或状态变化时),Flutter框架会调用状态对象的build()方法;
build()方法返回一个Widget Tree,这个树描述了应该如何在屏幕上呈现该widget;
StatefulElement会将自身作为BuildContext传入到build()方法中,以便在Widget Tree中可以使用context相关的功能;

build()方法返回的Widget Tree最终会被转换为一系列的RenderObject;
每个widget都有一个对应的RenderObject类型,用于实际的布局和绘制工作;
这个转换过程是通过Widget Tree的深度优先遍历来完成的,每个widget都会调用其自己的createElement()和build()方法来参与这个过程;
最终,每个widget都会与一个或多个RenderObject关联起来,形成一个Render object Tree;

一旦Render object Tree被构建完成,Flutter就会开始布局和绘制过程;
布局过程确定每个render object的大小和位置;
绘制过程则使用Skia图形库(或其他平台特定的图形API)来将render object渲染到屏幕上。

总结

Widget定义了用户界面的结构和样式,是声明性的;
Element是Widget的实例化对象,负责维护UI的状态并与RenderObject进行协调;
RenderObject负责实际的布局和绘制工作,使用Paint对象来执行绘图操作;
Paint定义了绘图操作的样式和效果。

相关文章:

  • 力扣188. 买卖股票的最佳时机 IV
  • cissp 第10章 : 物理安全要求
  • PHP中excel带图片数据导入
  • Centos 磁盘挂载和磁盘扩容(新加硬盘方式)
  • <HarmonyOS第一课>1~10课后习题汇总
  • 使用HttpSession和过滤器实现一个简单的用户登录认证的功能
  • ControlNet构图控制
  • PCL 格网法计算点云的占地面积
  • React16源码: React中创建更新的方式及ReactDOM.render的源码实现
  • 收到的字符串写入xml并且将这个xml写入.zip文件中
  • 【设计模式】工厂模式
  • 【动态规划】C++算法:446等差数列划分 II - 子序列
  • 带前后端H5即时通讯聊天系统源码
  • ES-极客学习第二部分ES 入门
  • 二叉树的层序遍历经典问题(算法村第六关白银挑战)
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 【技术性】Search知识
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • echarts的各种常用效果展示
  • HTTP请求重发
  • JAVA之继承和多态
  • leetcode讲解--894. All Possible Full Binary Trees
  • ViewService——一种保证客户端与服务端同步的方法
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 使用 QuickBI 搭建酷炫可视化分析
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • Python 之网络式编程
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​ssh免密码登录设置及问题总结
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (1)STL算法之遍历容器
  • (13):Silverlight 2 数据与通信之WebRequest
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (三)docker:Dockerfile构建容器运行jar包
  • (十六)串口UART
  • (一) storm的集群安装与配置
  • (转)jdk与jre的区别
  • (转载)Linux 多线程条件变量同步
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET 反射 Reflect
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .net 无限分类
  • .Net(C#)自定义WinForm控件之小结篇
  • .net访问oracle数据库性能问题
  • .net分布式压力测试工具(Beetle.DT)
  • .Net转前端开发-启航篇,如何定制博客园主题
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @hook扩展分析