Flutter进阶(6):详解 Key

news/2025/1/10 17:31:38/文章来源:https://www.cnblogs.com/linuxAndMcu/p/18664364

一、Key是什么?

用官方的说法就是:Key 是 Widget、Element 和 SemanticNodes 的唯一标识符。

组件在更新的时候,其状态的保存主要是通过判断组件的类型或者 key 值是否一致。因此,当各组件的类型不同的时候,类型已经足够用来区分不同的组件了,此时我们可以不必使用 key。但是如果同时存在多个同一类型的控件的时候,此时类型已经无法作为区分的条件了,我们就需要使用到 key。

二、Key的分类

Flutter key子类包含LocalKeyGlobalKey

  • 局部键(LocalKey):ValueKey、ObjectKey、UniqueKey

  • 全局键(GlobalKey): GlobalKey、GlobalObjectKey


2.1 UniqueKey

优点:

  • 唯一性:UniqueKey 保证每次都有一个唯一的标识符,防止小部件重复出现。
  • 功效(Efficacy): 非常适合创建有状态部件的新实例。

缺点:

  • 使用受限: 只有在每次都需要一个新实例时才使用 UniqueKey。过度使用可能会导致不必要的部件重建。
final Key key = UniqueKey();Widget build(BuildContext context) {return SomeStatefulWidget(key: key);
}

2.2 ValueKey

优点:

  • 基于值的识别: 用于根据特定值识别小部件,改善基于数据的小部件管理。
  • 自定义:允许您使用自定义值创建 key。

缺点:

  • 值依赖:如果值频繁变化,可能会导致不必要的小部件重建。
final Key key = ValueKey<String>('myValue');Widget build(BuildContext context) {return SomeStatefulWidget(key: key);
}

2.3 ObjectKey

优点:

  • 对象标识:允许根据对象的标识来区分对象,即使它们的值相同。

缺点:

  • 潜在的陷阱:可以引起混乱,如果不谨慎使用,特别是与类似的对象。
final Key key = ObjectKey(myObject);Widget build(BuildContext context) {return SomeStatefulWidget(key: key);
}

2.4 PageStorageKey

优点:

  • 状态保留:非常适合保留滚动位置和状态信息,增强用户体验,尤其是在分页视图中。
  • 性能提升:通过高效地保存和恢复小部件状态来提高性能。

缺点:

  • 复杂度:需要了解如何有效地管理状态和滚动位置。
final Key key = PageStorageKey<String>('pageKey');Widget build(BuildContext context) {return SomeStatefulWidget(key: key);
}

2.5 GlobalKey

优点:

  • 全局访问:提供从应用程序中的任何地方访问小部件的状态或属性,提高可管理性。
  • 交互性:允许从其父级外部与小部件进行交互。

缺点:

  • 潜在的内存泄漏:误用或不当处理可能导致内存泄漏。
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();Widget build(BuildContext context) {return Scaffold(key: scaffoldKey, ...);
}

下面重点介绍一下GlobalKey

三、GlobalKey详解

前面介绍 GlobalKey 支持全局访问,允许我们在 Widget 树之外访问该 Widget 的状态或属性。它通常用于在多个 Widget 之间共享状态、访问子 Widget 的方法或属性,以及执行一些全局操作。

下面用个代码案例来更好的理解:

// ignore_for_file: library_private_types_in_public_api
import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {// 定义 GlobalKey 用于获取按钮的状态final GlobalKey<_CounterButtonState> buttonKey = GlobalKey();MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('Counter App'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 使用 CounterButton,并传入 GlobalKeyCounterButton(key: buttonKey),const SizedBox(height: 20),// 在这里显示当前计数ElevatedButton(onPressed: () {// 当按钮被点击时,调用按钮的 increaseCount 方法buttonKey.currentState?.increaseCount();},child: const Text('Increase Count'),),],),),),);}
}// CounterButton Widget,用于显示当前计数
class CounterButton extends StatefulWidget {// 接收 GlobalKeyconst CounterButton({super.key});@override_CounterButtonState createState() => _CounterButtonState();
}class _CounterButtonState extends State<CounterButton> {int count = 0;// 增加计数的方法void increaseCount() {setState(() {count++;});}@overrideWidget build(BuildContext context) {return Text('Count: $count',style: const TextStyle(fontSize: 24),);}
}

效果图如下所示:

Flutter_widget_B.png


我们首先创建了一个GlobalKey,用于获取CounterButton的状态。然后我们在MyApp中使用CounterButton,并将这个GlobalKey传递给CounterButton

当按钮被点击时,我们通过GlobalKey获取CounterButton的状态,并调用其方法来更新计数。

可以看出GlobalKey允许我们在 Flutter 应用中跨 Widget 获取其他 Widget 的状态或执行操作。

更详细的内容可以看下这篇博客:Flutter 最熟悉的陌生人之 Key 全面解析回顾一下,上篇我们讲完 Flutter Widget 体系架构,其中在 - 掘金


参考:

前端 - Flutter Keys: 你的终极指南,让 widget 世界更快乐 - 程序员张张 - SegmentFault 思否

Flutter 中的 GlobalKey - -鹿- - 博客园

Flutter 详解 Key - ifgyong - 博客园


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

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

相关文章

数据的涟漪效应:实时数据赋能保险资产管理,打造数字化、信息化、智能化的保险新业态

本期内容以保险公司的具体案例为切入点,探讨数字化技术如何助力保险资产管理行业应对数据管理的挑战并实现创新突破。使用 TapData,化繁为简,摆脱手动搭建、维护数据管道的诸多烦扰,轻量替代 OGG, Kettle 等同步工具,以及基于 Kafka 的 ETL 解决方案,「CDC + 流处理 + 数…

KingbaseES RAC在线扩容案例

KingbaseES、KingbaseES RAC案例说明: KingbaseES RAC在两节点的基础上,执行在线扩容为3节点。 集群版本: test=# select version();version ---------------------KingbaseES V008R006 (1 row)集群架构:操作系统: [root@node210 KingbaseHA]# cat /etc/os-release NAME=&…

Xinference:企业级大模型推理和部署平台

导读 近年来,大语言模型(LLM,后简称大模型)的发展突飞猛进。本文将分享未来速度公司在开源领域以及大模型落地过程中的核心产品——Xinference,其定位是一个真正企业级的、严肃的大模型推理和部署平台。公司致力于在 LLMOps(大模型运维)过程中,帮助大家降低部署的成本和…

【Java开发】面对一个访问量比较高的API,我们应该如何去应对突然暴涨的流量呢?

一、流量管理与限流 1. 流量限制和速率限制: 例如,当请求频率超过预设阈值时,系统可以自动限制或拒绝额外的请求,从而保护后端服务免受过多请求的影响。 通过API网关或负载均衡器进行配置,以控制每个用户或IP的请求速率。 2. 使用限流算法: 令牌桶算法:适合应对瞬时突发…

高效团队协作:在线工具在酒店管理中的实践

1. 酒店运营的复杂性与信息管理的挑战 酒店行业是一个高度复杂和依赖信息的行业。从前台接待到客房服务,从市场营销到财务管理,每个环节都需要精准的数据对接与高效的沟通。然而,在传统管理模式下,信息传递通常依赖于邮件、电话或线下会议,不仅效率低下,还容易导致信息遗…

Centos7 离线安装nginx教程

步骤一:安装nginx三个依赖openssl 、pcre、zlib pcre:https://sourceforge.net/projects/pcre/files/pcre/8.45/(版本:pcre-8.45.tar.gz)zlib:http://www.zlib.net/(版本:zlib-1.2.13.tar.gz)oppenssl:https://www.openssl.org/source/(版本:openssl-1.1.0h.tar.gz…

JS-27 字符串方法_split()

split方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组 it|sxt|zifuchuan.split(|)//["it","sxt","zifuchuan"] 如果分割规则为空字符串,则返回数组的成员是原字符串的每一个字符。 a|b|c.split()//["a","|…

找不到 .NETFramework,Version=v4.0 的引用程序集问题

高版本操作系统默认安装.NETFramework4.6或以上时,系统用4.0的msbuild 命令编译导致 找不到4.0的程序集问题 1.下载nuget版本的资源包 https://www.nuget.org/packages/Microsoft.NETFramework.ReferenceAssemblies.net40/ microsoft.netframework.referenceassemblies.net40.…

嵌入式截屏工具-gsnap移植 arm平台

# 目录 - [前言](#前言) - [正文](#正文)- [原理](#原理)- [环境](#环境)- [详细流程](#详细流程)- [使用](#使用) - [参考](#参考)# 正文 ## 原理 ### 前提条件: 嵌入式机器要支持`/dev/fb0`这个设备节点。不然,这个工具基本就使用不了了。### 原理: 由于 Linux 系统的 Frame…

AIME2019 I

AIME2019 I 的题目订正。√√√√ √√.√√ ...√. \(= 9\) https://artofproblemsolving.com/wiki/index.php/2019_AIME_I_Problems P4 寄啦! 唐题。分讨 substitution 的次数即可。 P5 对啦! DP。 令 \(f_{x,y}\) 为走到 \((x,y)\) 的概率。边界情况为 \(f_{4,4} = 1\)。答…

通过本地私有的镜像仓库harbor解决网络原因导致的jdk无法加载而造成的docker打包错误.v2.250110

​各种网络原因,或是docker.io无法访问,或是阿里的镜像源故障,导致java打包发布的时候报错,很影响代码发布的质量。解决思路:墙出去把jdk下载下来,代码使用本地的harbor库进行引用,一劳永逸。此解决方法也适用于国外优质不频繁变动的镜像源的本地化使用。解决方法 1. 自…

[题目记录]AGC005E Sugigma: The Showdown

一道通过自己生成思路做出的思维题 . 通过分析博弈过程发现问题其实没有那么复杂 , 然后层层分析转化问题即可 .AGC005E Sugigma: The Showdown 题意 给出两棵树 , 点的编号相同 , 连边方式不同 . 初始 A 在树 \(a\) 上的点 \(x\) , B 在树 \(b\) 上的点 \(y\) , 两人轮流走 , …