Flutter进阶(6):详解 Key
一、Key是什么?
用官方的说法就是:Key 是 Widget、Element 和 SemanticNodes 的唯一标识符。
组件在更新的时候,其状态的保存主要是通过判断组件的类型或者 key 值是否一致。因此,当各组件的类型不同的时候,类型已经足够用来区分不同的组件了,此时我们可以不必使用 key。但是如果同时存在多个同一类型的控件的时候,此时类型已经无法作为区分的条件了,我们就需要使用到 key。
二、Key的分类
Flutter key子类包含LocalKey
和GlobalKey
。
-
局部键(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});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 使用 CounterButton,并传入 GlobalKey
CounterButton(key: buttonKey),
const SizedBox(height: 20),
// 在这里显示当前计数
ElevatedButton(
onPressed: () {
// 当按钮被点击时,调用按钮的 increaseCount 方法
buttonKey.currentState?.increaseCount();
},
child: const Text('Increase Count'),
),
],
),
),
),
);
}
}
// CounterButton Widget,用于显示当前计数
class CounterButton extends StatefulWidget {
// 接收 GlobalKey
const CounterButton({super.key});
@override
_CounterButtonState createState() => _CounterButtonState();
}
class _CounterButtonState extends State<CounterButton> {
int count = 0;
// 增加计数的方法
void increaseCount() {
setState(() {
count++;
});
}
@override
Widget build(BuildContext context) {
return Text(
'Count: $count',
style: const TextStyle(fontSize: 24),
);
}
}
效果图如下所示:
我们首先创建了一个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 - 博客园
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
2019-01-10 C++入门知识点总结