Flutter知识点 --- key

Flutter 中的 Key 对象在Widget树的构建、更新和状态管理中扮演着重要角色。它主要用于帮助Flutter框架在Widget树发生变动时正确地识别和保留Widget的对应关系,以及在某些情况下维护状态。下面是Key的作用与原理的详细阐述:

Key的作用

  1. 标识Widget的唯一性

    • Key 提供了一个唯一的标识符,用于区分同一类型但具有不同逻辑意义或状态的Widget。即使两个Widget在类型、属性等方面完全相同,只要它们的Key不同,Flutter就会认为它们是独立的实体。
  2. 优化Widget树重建

    • 当Widget树发生变更时,Flutter会使用一种称为“增量构建”的算法来决定哪些部分需要重新构建,哪些可以复用。Key在这里起到了关键作用:它帮助Flutter框架识别出哪些Widget是新插入的、哪些Widget被移动了位置、哪些Widget被替换掉了,以及哪些Widget可以保持不变。
  3. 维持Stateful Widget的状态

    • 对于StatefulWidgetKey可以帮助保持其状态在Widget树结构变化时不受影响。如果一个StatefulWidget在重建过程中保持了相同的Key,那么其对应的State对象会被保留,避免状态丢失或重新初始化。
  4. 全局访问和定位Widget

    • GlobalKey 特殊类型允许开发者从应用程序的任何地方访问到与之关联的StateElement。这对于需要跨层级访问或操纵特定Widget状态的场景非常有用,比如实现复杂的动画、管理全局状态等。

Key的原理

Widget、Element与RenderObject的关系

  • 在Flutter中,每个Widget对应一个Element,每个Element又关联一个RenderObject。Key主要作用于Element层面。

增量构建与Diff算法

  • 当Widget树发生变更时,Flutter会进行增量构建。它会比较新旧两棵Widget树,通过对比Key值来判断Widget的增删、移动或更新。
    • 若新旧两个Widget具有相同的Key且类型相同,则认为是同一个Widget的不同版本,框架会尝试复用现有Element,更新其属性,而不是销毁旧Widget并创建新Widget。
    • 若没有提供Key或者Key不同,则认为是两个不同的Widget,旧Widget对应的Element将被销毁,新Widget会创建新的Element。

Stateful Widget与State的关联

  • 对于StatefulWidgetState对象存储在与其关联的Element中。当StatefulWidgetKey保持不变时,即使其在树中的位置或其父Widget发生了变化,对应的State也会被保留下来,避免了不必要的初始化和状态丢失。

GlobalKey的工作原理

  • GlobalKey在Flutter中是全局唯一的,它在Element树中注册自己,使得无论何时何地,只要知道GlobalKey,就能找到对应的ElementState
    • 通过GlobalKey.currentStateGlobalKey.findAncestorStateOfType等方法,可以从任意位置访问到与之关联的State,实现跨层级的状态操作或组件间的直接通信。

总结

Flutter中的Key是用于唯一标识Widget的重要工具,它在Widget树的构建和更新过程中起到关键作用,帮助框架有效地进行增量构建,避免不必要的重绘和状态丢失。特别是对于StatefulWidgetKey确保了状态的正确维护。而GlobalKey则提供了跨越Widget树层级访问和控制特定Widget或其状态的能力。理解和恰当使用Key有助于提升Flutter应用的性能和状态管理的准确性。

Flutter中的Key在以下几种常见场景中尤其有用:

  1. 列表项的复用与状态保持

    • 在构建长列表时,通常使用ListView.builder等可滚动列表组件。为列表项(如ListTile或自定义Widget)指定唯一的Key(如ValueKey(index)ObjectKey(item.id)),可以帮助Flutter准确地判断列表项在更新时是被重新排序、添加、删除还是内容改变。这样可以确保正确的状态保留(如保持滚动位置、文本输入框的文本状态等),同时提高列表滚动时的性能,因为只有实际发生变化的项才会被重新构建。
  2. 状态ful Widget的位置变化或重新排序

    • 如果一个StatefulWidget可能会在树中移动位置(如卡片拖拽排序),为其赋予Key可以确保即使其位置改变,其内部状态也能得到保留,不会因位置移动而丢失。
  3. 动画与过渡效果

    • 在实现复杂的动画或过渡效果时,可能需要对某个Widget的State进行直接操作。通过为该StatefulWidget分配一个GlobalKey,可以在动画控制器或其他辅助类中轻松访问到该State,从而控制动画状态、触发过渡等。
  4. 表单控件的状态管理

    • 在表单中,用户可能需要填写多个同类输入字段(如多个文本框)。为每个输入控件分配一个Key(如基于字段名的ValueKey),可以确保即使表单布局发生变化或输入控件重新生成,已输入的数据和验证状态仍能正确关联到对应的控件。
  5. 页面路由与导航

    • 使用PageStorageKey可以为每个路由或页面指定一个独特的标识,这样即使页面被暂时移除出视图层次(如使用Navigator进行页面切换),当用户返回时,页面的滚动位置、展开/折叠状态等用户交互产生的状态仍能得以恢复。
  6. 测试中的Widget定位

    • 在编写Widget测试时,为特定Widget分配Key有助于在测试代码中精确地查找和交互这些Widget,简化测试用例的编写和调试。

总的来说,Key在涉及Widget复用、状态保留、跨层级状态访问、动画控制、表单管理、页面路由以及测试等场景中都有其重要作用。正确使用Key可以显著提升Flutter应用的用户体验、性能以及代码的可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/819159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源相机管理库Aravis例程学习(二)——连续采集multiple-acquisition-main-thread

开源相机管理库Aravis例程学习(二)——连续采集multiple-acquisition-main-thread 简介例程代码函数说明arv_camera_set_acquisition_modearv_camera_create_streamarv_camera_get_payloadarv_buffer_newarv_stream_push_bufferarv_camera_start_acquisi…

目标检测YOLO实战应用案例100讲-基于轻量化神经网络的目标检测算法研究与应用(续)

目录 轻量化目标检测模型的参数量化 4.1引言 4.2模型量化的原理及过程 4.3实验结果及分析

如何看待2023年图灵奖

目录 1.概述 2.计算复杂性理论 3.随机性和伪随机性 4.学术生涯和领导力 1.概述 图灵奖(Turing Award),全称A.M.图灵奖(ACM A.M Turing Award),是由计算机领域的最高学术机构——美国计算机协会&#xf…

ElasticSearch 集群添加用户安全认证功能(设置访问密码)

前言 在6.8之前免费版本并不包含安全认证功能,之后版本有开放一些基础认证功能;为了防止各种事故,一般都会设置es集群的访问密码;但是在我尝试设置访问密码的时候发现,设置访问密码的前提必须要设置集群证书&#xff0…

java:多线程

多线程 在java程序中同时执行多个线程,每个线程独立执行不同的任务. 可以提高程序的性能和资源利用率,增加程序的并发性. 多线程的作用 1,提高程序性能 可以将一个任务分解成多个子任务并行处理,从而提高程序的运行速度 2,提高资源利用率 可以更好地利用CPU资源,提高CPU…

如何实现Windows RDP 远程桌面异地跨网连接

Windows RDP远程桌面的应用非常广泛。远程桌面协议(RDP)是一个多通道(multi-channel)的协议,让使用者(所在计算机称为用户端或本地计算机)连上提供微软终端机服务的计算机(称为服务端或远程计算机)。大部分的Windows版本都有用户端所需软件,有些其他操作…

Python Flask Web 框架-API接口开发_4

一、1、安装 Falsk 当前用户安装 pip3 install --user Flask 确认安装成功: 进入python交互模式看下Flask的介绍和版本: $ python3>>> import flask >>> print(flask.__doc__)flask~~~~~A microframework based on Werkzeug. Its …

病毒繁殖-第12届蓝桥杯选拔赛Python真题精选

[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第52讲。 病毒繁殖&#xf…

Linux userdel命令教程:如何删除用户账户及其相关文件(附实例详解和注意事项)

Linux userdel命令介绍 userdel命令在Linux系统中用于删除用户账户及其相关文件。这个命令主要修改系统账户文件,删除所有引用到用户名的条目。 Linux userdel命令适用的Linux版本 userdel命令在大多数Linux发行版中都可以使用,包括但不限于Debian、U…

数据结构与算法——23.哈希冲突及其解决方法

这篇文章我们主要讲一下哈希冲突及其解决方法。 目录 1.哈希冲突的介绍 2.解决哈希冲突的方法 2.1 开放地址法 2.1.1 线性探测法 2.1.2 平方探测法(二次探测法) 2.2再哈希法 2.3链地址法 2.4建立公共溢出区 3.总结 1.哈希冲突的介绍 首先&…

静态路由

路由器主要功能是确定发送数据包的最佳路径以及将数据包从一个网络传送到另一个网络。路由是所有数据网络的核心所在,它通过搜索存储在路由表中的路由信息将数据包从源传送到目的地,所以说路由表是路由器工作的核心。路由器构建路由表的方式通常有3种:直…

vue快速入门(二十五)本地存储与初始化使用

注释很详细&#xff0c;直接上代码 上一篇 新增内容 本地获取数据数据存储到本地 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial…

【浪漫 罗盘时钟 Js、css实现(附源代码) 美化版本】,前端面试必问的HashMap

先自我介绍一下&#xff0c;小编浙江大学毕业&#xff0c;去过华为、字节跳动等大厂&#xff0c;目前阿里P7 深知大多数程序员&#xff0c;想要提升技能&#xff0c;往往是自己摸索成长&#xff0c;但自己不成体系的自学效果低效又漫长&#xff0c;而且极易碰到天花板技术停滞…

java发送短信

1、参考&#xff1a;Java_消息&短信 MSGSMS_开发指南_代码样例_X-WSSE认证 参考"发送短信"这一块的代码 2、执行main方法&#xff0c;报错了&#xff0c;报错如下&#xff1a; {"code":"E000027","description":"Invalid …

WebKit简介及工作流程

文章目录 一、WebKit简介二、WebKit结构三、Webkit工作流程四、WebKit常见问题五、WebKit优点六、相关链接 一、WebKit简介 WebKit是一个开源的浏览器引擎&#xff0c;它的起源可以追溯到2001年&#xff0c;当时苹果公司推出了其首款基于Unix的操作系统Mac OS X。在2002年&…

欧拉公式;傅里叶变换;耳朵:声波(音频)眼睛:光波(图像) 大脑:傅里叶快速变换

目录 复分析 复数指数函数 欧拉公式 a点向量,方向和长度的向量;

最短网络kruskal算法

题目描述 农民约翰被选为他们镇的镇长&#xff01;他其中一个竞选承诺就是在镇上建立起互联网&#xff0c;并连接到所有的农场。当然&#xff0c;他需要你的帮助。约翰已经给他的农场安排了一条高速的网络线路&#xff0c;他想把这条线路共享给其他农场。为了用最小的消费&…

【Java开发指南 | 第七篇】静态变量生命周期、初始化时机及静态变量相关性质

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 生命周期初始化时机常量和静态变量的区别静态变量相关性质静态变量的访问修饰符静态变量的线程安全性静态变量的命名规范 生命周期 生命周期&#xff08;Lifecycle&#xff09;是指一个对象从创建到销毁的整个…

NVIC简介

NVIC&#xff08;Nested Vectored Interrupt Controller&#xff09;是ARM处理器中用于中断管理的一个重要硬件模块。它负责处理来自多个中断源的中断请求&#xff0c;并根据中断的优先级来安排处理器执行相应的中断服务例程&#xff08;ISR&#xff09;。NVIC是ARM Cortex-M系…

光电传感器的工作原理简介

光电传感器是一种利用光电效应将光信号转换为电信号的传感器。 工作原理 光照射&#xff1a;光电传感器通过光源&#xff08;如LED或激光&#xff09;照射在其表面。 光电转换&#xff1a;光线与传感器材料发生光电反应&#xff0c;产生电信号。这种转换过程涉及到光子与电子的…