Flutter进阶(6):详解 Key

 


一、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});

  @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),
    );
  }
}

效果图如下所示:

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 - 博客园


posted @   fengMisaka  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
历史上的今天:
2019-01-10 C++入门知识点总结
点击右上角即可分享
微信分享提示