Flutter:key的作用原理(LocalKey ,GlobalKey)
第一段代码实现的内容:创建了3个块,随机3个颜色,每次点击按钮时,把第一个块删除
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_one/demo.dart';void main() {runApp(const App());
}class App extends StatelessWidget {const App({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return const MaterialApp(home: KeyDemo(),);}
}class KeyDemo extends StatefulWidget {const KeyDemo({Key? key}) : super(key: key);@overrideState<KeyDemo> createState() => _KeyDemoState();
}class _KeyDemoState extends State<KeyDemo> {// 生成三个无状态的块List<Widget> items = [StlItem('1'),StlItem('2'),StlItem('3')];@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('KeyDemo'),centerTitle: true,),body: Row(mainAxisAlignment: MainAxisAlignment.center,children: items,),floatingActionButton: FloatingActionButton(child: Icon(Icons.add),onPressed: (){setState(() {items.removeAt(0); // 点击按钮把第一个删除});}),);}
}
先调用无状态的
StatelessWidget
,当删除发生时看看效果
class StlItem extends StatelessWidget {final String title;StlItem(this.title,{Key? key}) : super(key: key);// 随机的颜色final color = Color.fromRGBO(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1.0);@overrideWidget build(BuildContext context) {return Container(width: 100,height: 100,child: Text(title),color: color,);}
}
发生删除时:
删除后
总结发现,如果是无状态的StatelessWidget
即使不传key:StlItem(this.title,{Key? key}) : super(key: key);
也能正常删除。
下面看下有状态的
StatelessWidget
,不传key会出现什么BUG
// 第一段代码中:生成三个有状态的块
List<Widget> items = [StfulItem('1'),StfulItem('2'),StfulItem('3')
];// 有状态
class StfulItem extends StatefulWidget {final String title;StfulItem(this.title,{Key? key}) : super(key: key);@overrideState<StfulItem> createState() => _StfulItemState();
}class _StfulItemState extends State<StfulItem> {// 随机的颜色final color = Color.fromRGBO(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1.0);@overrideWidget build(BuildContext context) {return Container(width: 100,height: 100,child: Text(widget.title),color: color,);}
}
删除前
删除后
发现问题了:我删除的是第一条数据,发现文字1
正常删除,但是颜色怎么是把颜色3
给删除了呢??
源码中,StatelessWidget
和StatefulWidget
都继承Widget
abstract class StatefulWidget extends Widget{}
而在Widget
中有这样一个方法,Flutter的增量渲染就是通过canUpdate
来判断哪里需要更新数据。
static bool canUpdate(Widget oldWidget, Widget newWidget) {return oldWidget.runtimeType == newWidget.runtimeType&& oldWidget.key == newWidget.key;
}
Flutter中的3棵树中,Widget树和Element树
每创建一个Widget
,都会有对应的Element
当删除第一个Widget
,Element
就会调用canUpdate
更新数据,Element
是按顺序判断,它会拿Element111
和删除后的Widget222
进行对比
oldWidget.runtimeType == newWidget.runtimeType
旧的部件类型和新的部件类型是一样的,oldWidget.key == newWidget.key;
旧的没有传key和新的也没传key,结果那就是true
,增量渲染发现可以复用,Element111
就指向了Widget222
最后对比到Element333
,发现Widget
树中已经没有了,Element333
就被删除了。
那么颜色为什么会错了,因为颜色是保存在State
中,State
是保存在Element
中,所以最后一个颜色canUpdate
时被删除了。
加上key之后解决这个BUG
List<Widget> items = [StfulItem('1',key: const ValueKey('1'),),StfulItem('2',key: const ValueKey('2'),),StfulItem('3',key: const ValueKey('3'),)
];
key的原理
Key本身是一个抽象类,有一个工厂构造方法,创建ValueKey
直接子类主要有:LocalKey 和 GlobalKeyGlobalKey:帮助我们访问某个Widget的信息LocalKey :它用来区别哪个Element保留,哪个Element要删除ValueKey 以值作为参数(数字、字符串)ObjectKey:以对象作为参数UniqueKey:创建唯一标识
GlobalKey使用
import 'package:flutter/material.dart';
class GlobalKeyDemo extends StatelessWidget {// 定义:GlobalKey<拿谁的数据> 变量 = GlobalKey();final GlobalKey<_childPageState> _globalKey = GlobalKey();GlobalKeyDemo({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('GlobalKeyDemo'),),body: childPage(key: _globalKey,),floatingActionButton: FloatingActionButton(onPressed: (){// _globalKey 就能访问到 _childPageState 中的属性,进行修改_globalKey.currentState!.setState((){_globalKey.currentState!.data = 'hello word';_globalKey.currentState!.count++;});},child: const Icon(Icons.add),),);}
}class childPage extends StatefulWidget {const childPage({Key? key}):super(key: key);@overrideState<childPage> createState() => _childPageState();
}class _childPageState extends State<childPage> {int count = 0;String data = 'heelo';@overrideWidget build(BuildContext context) {return Column(children: [Text(count.toString()),Text(data),],);}
}
除了定义GlobalKey
外,还可以使用InheritedWidget
数据共享。
相关文章:
Flutter:key的作用原理(LocalKey ,GlobalKey)
第一段代码实现的内容:创建了3个块,随机3个颜色,每次点击按钮时,把第一个块删除 import dart:math; import package:flutter/material.dart; import package:flutter_one/demo.dart;void main() {runApp(const App()); }class App…...
R语言基础入门详解
文章目录 R语言基础入门详解一、引言二、R语言环境搭建1、安装R和RStudio1.1、步骤1.2、获取工作目录 三、R语言基础2、语法基础2.1、赋值操作2.2、注释 3、数据类型与结构3.1、向量3.2、矩阵 4、基本操作4.1、数据读取4.2、数据可视化 四、R语言使用示例4.1、统计分析示例4.2、…...
django启动项目报错解决办法
在启动此项目报错: 类似于: django.core.exceptions.ImproperlyConfigured: Requested setting EMOJI_IMG_TAG, but settings are not c启动方式选择django方式启动,以普通python方式启动会报错 2. 这句话提供了对遇到的错误的一个重要线索…...
详细描述一下Elasticsearch搜索的过程?
大家好,我是锋哥。今天分享关于【详细描述一下Elasticsearch搜索的过程?】面试题。希望对大家有帮助; 详细描述一下Elasticsearch搜索的过程? Elasticsearch 的搜索过程是其核心功能之一,允许用户对存储在 Elasticsea…...
Spring、SpringMVC、SpringBoot、Mybatis小结
Spring Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架) Spring框架的核心特性包括依赖注入(Dependency Injection ,DI)、面向切面编程(Aspe…...
.NET 9 运行时中的新增功能
本文介绍了适用于 .NET 9 的 .NET 运行时中的新功能和性能改进。 文章目录 一、支持修剪的功能开关的属性模型二、UnsafeAccessorAttribute 支持泛型参数三、垃圾回收四、控制流实施技术.NET 安装搜索行为性能改进循环优化感应变量加宽Arm64 上的索引后寻址强度降低循环计数器可…...
Linux下安装mysql8.0版本
先确定我的下载安装的目录,安装文件是下载在 /opt/install 目录下面 (安装地址不同的话注意修改地址) 1.在线下载 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz2.解压 tar -xvf mysql-8.0.20-linux-glibc2.12-x86_64.t…...
kvm-dmesg:从宿主机窥探虚拟机内核dmesg日志
在虚拟化环境中,实时获取虚拟机内核日志对于系统管理员和开发者来说至关重要。传统的 dmesg 工具可以方便地查看本地系统的内核日志,但在KVM(基于内核的虚拟机)环境下,获取虚拟机内部的内核日志则复杂得多。为了简化这…...
植物明星大乱斗15
能帮到你的话,就给个赞吧 😘 文章目录 player.hplayer.cppparticle.hparticle.cpp player.h #pragma once #include <graphics.h> #include "vector2.h" #include "animation.h" #include "playerID.h" #include &…...
go-zero(三) 数据库操作
go-zero 数据库操作 在本篇文章中,我们将实现一个用户注册和登录的服务。我们将为此构建一个简单而高效的 API,包括请求参数和响应参数的定义。 一、Mysql连接 1. 创建数据库和表 在 MySQL 中创建名为 test_zero的数据库,并创建user 表 …...
SQL面试题——间隔连续问题
间隔连续问题 某游戏公司记录的用户每日登录数据如下 +----+----------+ | id| date| +----+----------+ |1001|2021-12-12| |1001|2021-12-13| |1001|2021-12-14| |1001|2021-12-16| |1001|2021-12-19| |1001|2021-12-20| |1002|2021-12-12| |1002|2021-12-16| |1002|…...
vim配置 --> 在创建的普通用户下
在目录/etc/ 下面,有个名为vimrc 的文件,这是系统中公共的vim配置文件对所有用户都有效 我们现在创建一个普通用户 dm 创建好以后,我们退出重新链接 再切换到普通用户下 再输入密码(是不显示的,输入完后,…...
(计算机毕设)基于SpringBoot+Vue的房屋租赁系统的设计与实现
博主可接毕设设计!!! 各种毕业设计源码只要是你有的题目我这里都有源码 摘 要 社会的发展和科学技术的进步,互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。互…...
【含开题报告+文档+PPT+源码】基于SpringBoot的医院药房管理系统
开题报告 在科技迅速发展的今天,各行各业都在积极寻求与现代技术的融合,以提升自身的运营效率和竞争力。医疗行业作为关乎国计民生的关键领域,其信息化建设的步伐尤为迅速。医院药房作为医疗体系中的核心环节,其管理效率和服务质…...
基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 系统首页界面图 数码板…...
Linux-第2集-打包压缩 zip、tar WindowsLinux互传
欢迎来到Linux第2集,这一集我会非常详细的说明如何在Linux上进行打包压缩操作,以及解压解包 还有最最重要的压缩包的网络传输 毕竟打包压缩不是目的,把文件最终传到指定位置才是目的 由于打包压缩分开讲没有意义,并且它们俩本来…...
项目进度计划表:详细的甘特图的制作步骤
甘特图(Gantt chart),又称为横道图、条状图(Bar chart),是一种用于管理时间和任务活动的工具。 甘特图由亨利劳伦斯甘特(Henry Laurence Gantt)发明,是一种通过条状图来…...
Cargo Rust 的包管理器
Cargo->Rust 的包管理器 Cargi简介Cargo 的主要功能1. 创建项目2. 管理依赖3. 构建项目4. 运行项目5. 测试代码6. 检查代码7. 生成文档8. 发布和分享包 Cargo 的核心文件1. Cargo.toml2. Cargo.lock **Cargo 的生态系统** 常用命令总结Hello, Cargo! 示例 Cargi简介 Cargo …...
【Rust 编程语言工具】rustup-init.exe 安装与使用指南
rustup-init.exe 是用于安装和管理 Rust 编程语言工具链的 Windows 可执行文件。Rust 是一种系统级编程语言,旨在提供安全、并发和高性能的功能。rustup-init.exe 是官方提供的安装器,用于将 Rust 安装到 Windows 操作系统中,并配置相关环境。…...
集群聊天服务器(12)nginx负载均衡器
目录 负载均衡器nginx负载均衡器优势 如何解决集群聊天服务器跨服务器通信问题?nginx的TCP负载均衡配置nginx配置 负载均衡器 目前最多只能支持2w台客户机进行同时聊天 所以要引入集群,多服务器。 但是客户连哪一台服务器呢?客户并不知道哪一…...
数据挖掘英语及概念
分类 classify 上涨或跌 回归 regression 描述具体数值 分类模型评估 1.混淆(误差)矩阵 confusion matrix 2.ROC曲线 receiver operating characteristic curve 接收者操作特征曲线 3.AUC面积 area under curve ROC曲线下与坐标轴围成的面积&#x…...
springboot第82集:消息队列kafka,kafka-map
官网下载链接:https://kafka.[apache].org/downloads 我下载的是[Scala]2.12 - kafka_2.12-3.1.0.tgz kafka只需要解压下载的压缩包就行了,我这里解压的路径是D:\kafka_2.12-3.1.0,kafka的运行需要依赖zookeeper,当前版本已经内置…...
sql server查看当前正在执行的sql
#统计某类sql执行次数,并按总体cpu消耗时间降序排序 with a as ( select er.session_id,db_name(er.database_id) as DBNAME,sy.last_batch AS 最后执行时间, er.cpu_time ,er.total_elapsed_time/1000 as sum_elapsed_time_s, CAST(csql.text AS varchar(8000)) A…...
STM32设计学生宿舍监测控制系统-分享
目录 前言 一、本设计主要实现哪些很“开门”功能? 二、电路设计原理图 电路图采用Altium Designer进行设计: 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 本项目旨在利用STM32单片机为核心,结合传感器技术、无线通信技…...
HAproxy 详解
一、基本概念 1.1 什么是 HAproxy? HAproxy(High Availability Proxy)是一个开源的高性能负载均衡器和反向代理服务器,它主要用于在网络上分发流量,以提高网站或应用程序的可用性和性能。HAproxy 可以处理大量的并发…...
间接采购管理:主要挑战与实战策略
间接采购支出会悄然消耗掉企业的现金流,即使是管理完善的公司也难以避免。这是因为间接支出不直接关联特定客户、产品或项目,使采购人员难以跟踪。但正确管理间接支出能为企业带来显著收益——前提是要有合适的工具。本文将分享管理间接支出的关键信息与…...
2411rust,正与整128
原文 长期以来,Rust在x86-32和x86-64架构上128位整数的对齐与C语言不一致.最近已解决此问题,但该修复带来了一些值得注意的效果. 作为用户,除非如下,否则不用担心: 1,假设i128/u128对齐,而不是用align_of 2,忽略improper_ctypes*检查,并在FFI中使用这些类. 除x86-32和x86-64…...
将 HTML 转换为 JSX:JSX 和 JSX 规则
JSX 是 JavaScript 的语法扩展。您可以在 JavaScript 文件中编写 HTML 格式。 它基于 Web、Html、Css 和 JavaScript。Web 开发人员将页面内容分别编写为 Html 文件,将设计编写为 Css 文件,将逻辑编写为 JavaScript 文件。 须知 : JSX 是一个…...
将 FastAPI 部署到生产服务器(一套 全)
将 FastAPI 部署到生产服务器(全) 文章目录 将 FastAPI 部署到生产服务器(全)一、前言二、Fastapi项目 生产环境配置1. 准备环境2. 编写 FastAPI 应用3. 使用 Uvicorn 运行应用4. 配置生产级服务器 Gunicorn4.1 配置 Gunicorn 和 …...
题解 洛谷 Luogu P1873 [COCI 2011/2012 #5] EKO / 砍树 二分答案 C/C++
题目传送门: P1873 [COCI 2011/2012 #5] EKO / 砍树 - 洛谷 | 计算机科学教育新生态https://www.luogu.com.cn/problem/P1873思路: 很简单的二分答案 每次找区间中点 m,判断以 m 为高度砍下的木头是否够 h 即可 代码: #defin…...
网站建设asp编程/电商中seo是什么意思
前奏 我们都知道 nginx 是一款优秀的反向代理服务,用过 nginx 的也应该都知道 upstream,upstream 节点一般置于 http 节点大括号中,常规在 upstream 中配置需要被负载均衡的服务器列表。 比较多的使用做如下示意: #user nobody…...
浏阳市政府门户网站/东莞好的网站国外站建设价格
Linux应用 编程深入 语言编程标准C程序设计七---经典C11程序设计 以下内容为阅读: 《标准C程序设计》(第7版) 作者:E. Balagurusamy(印), 李周芳译 清华大学出版社…...
购物网站源码/互动营销成功案例
\ 看新闻很累?看技术新闻更累?试试下载InfoQ手机客户端,每天上下班路上听新闻,有趣还有料!\\\Oracle提出了JEP 181“基于嵌套的访问控制”,即“Nestmate”。该JEP将是对Java平台的一次技术提升,…...
什么是网站设计与建设/保定网站推广公司
xStream可以Java和xml相互转换。下面主要说明xstream读取xml文件(和xstream将Java转化成xml差不多)。本次学习用到的是xstream1.4.7 项目中使用到的xml文件 <config name"personconfig"><!-- <add> --> <!-- 使用addImpl…...
网站推广策划案例/百度搜索收录入口
java flush控制台类flush()方法 (Console Class flush() method) flush() method is available in java.io package. flush()方法在java.io包中可用。 flush() method is used to flush this Console and ready for any output to be printed immediately. flush()方法用于刷新…...
安徽网站建设哪家好/网站建设的公司
2019独角兽企业重金招聘Python工程师标准>>> Frink:为物理计算设计的编程语言 作者:Alen 翻译:赖信涛 责编:仲培艺 Frink是一个实用的计算工具,也算是一种专为物理计算而设计的编程语言。它能让物理计算变得…...