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

Flutter key:LocalKey(局部)、GlobalKey(全局)

在Flutter中,Key是不能重复使用的,所以Key一般用来做唯一标识。组件在更新的时候,其状态的保
存主要是通过判断组件的类型或者key值是否一致。因此,当各组件的类型不同的时候,类型已经足够
用来区分不同的组件了,此时我们可以不必使用key。但是如果同时存在多个同一类型的控件的时候,
此时类型已经无法作为区分的条件了,我们就需要使用到key。
Flutter key子类包含 LocalKey 和 GlobalKey 。
局部键(LocalKey):ValueKey、ObjectKey、UniqueKey
全局键(GlobalKey): GlobalKey、GlobalObjectKey
ValueKey (值key)
把一个值作为key ,UniqueKey(唯一key)程序生成唯一的Key,当我们不知道
如何指定ValueKey的时候就可以使用UniqueKey,ObjectKey(对象key)把一个对象实例作为key。
GlobalKey(全局key)
GlobalObjectKey(全局Objec key,和ObjectKey有点类似)

LocalKey

LocalKey只在当前的组件树有效

GlobalKey的使用

GlobalKey就类似于全局变量
class MyKey extends StatelessWidget {
const MyKey({super.key}); @override
Widget build(BuildContext context) {
print(MediaQuery.of(context).orientation); //监听屏幕方向(横竖)
return MyApp();
}
} class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
} class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
} class _MyHomePageState extends State<MyHomePage> {
List<Widget> list = [];
final GlobalKey _key1 = GlobalKey();
final GlobalKey _key2 = GlobalKey();
final GlobalKey _key3 = GlobalKey();
@override
void initState() {
// TODO: implement initState
super.initState();
list = [
Box(
key: _key1,
color: Colors.blue,
),
Box(
key: _key2,
color: Colors.red,
),
Box(
key: _key3,
color: Colors.orange,
)
];
} @override
Widget build(BuildContext context) {
print(MediaQuery.of(context).orientation);
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
list.shuffle(); //打乱list的顺序
});
},
child: const Icon(Icons.refresh),
),
appBar: AppBar(
title: const Text('Title'),
),
body: Center(
child: MediaQuery.of(context).orientation == Orientation.portrait
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: list,
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: list,
),
),
);
}
} class Box extends StatefulWidget {
Color color;
Box({super.key, required this.color});
@override
State<Box> createState() => _BoxState();
} class _BoxState extends State<Box> {
int _count = 0;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 100,
width: 100,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(widget.color)),
onPressed: () {
setState(() {
_count++;
});
},
child: Center(
child: Text("$_count"),
),
),
);
}
}

GlobalKey 获取子组件

globalKey.currentState 可以获取子组件的状态,执行子组件的方法,globalKey.currentWidget可以获
取子组件的属性,_globalKey.currentContext!.findRenderObject()可以获取渲染的属性。
import 'package:flutter/material.dart';

class MyKey extends StatelessWidget {
const MyKey({super.key}); @override
Widget build(BuildContext context) {
return MyApp();
}
} class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
} class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
} class _HomePageState extends State<HomePage> {
final GlobalKey _globalKey = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
//1、获取子组件的状态 调用子组件的属性
var state = (_globalKey.currentState as _BoxState);
setState(() {
state._count++;
});
state.run(); //调用子部件的run方法
//2、获取子组件的属性(了解)
var box = (_globalKey.currentWidget as Box);
print(box.color);
//3、获取子组件渲染的属性(了解)
var renderBox =
(_globalKey.currentContext!.findRenderObject() as RenderBox);
print(renderBox.size);
},
),
appBar: AppBar(
title: const Text('Title'),
),
body: Center(
child: Box(
key: _globalKey,
color: Colors.red,
),
),
);
}
} class Box extends StatefulWidget {
final Color color; const Box({Key? key, required this.color}) : super(key: key);
@override
State<Box> createState() => _BoxState();
} class _BoxState extends State<Box> {
int _count = 0;
run() {
print("我是子部件的run方法");
} @override
Widget build(BuildContext context) {
return SizedBox(
height: 100,
width: 100,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(widget.color)),
onPressed: () {
setState(() {
_count++;
});
},
child: Center(
child: Text("$_count"),
),
),
);
}
}

Widget Tree、Element Tree 和 RenderObject Tree

Flutter应用是由是Widget Tree、Element Tree 和 RenderObject Tree组成
Widget可以理解成一个类,Element可以理解成Widget的实例,Widget与Element的关系可以是一对
多,一份配置可以创造多个Element实例

默认情况下面,当Flutter同一个 Widget的大小,顺序变化的时候,FLutter不会改变Widget的state。 

28、Flutter Key详解的更多相关文章

  1. Flutter 布局详解

    本文主要介绍了Flutter布局相关的内容,对相关知识点进行了梳理,并从实际例子触发,进一步讲解该如何去进行布局. 1. 简介 在介绍Flutter布局之前,我们得先了解Flutter中的一些布局相关 ...

  2. React之key详解

    一个例子 有这样的一个场景如下图所示,有一组动态数量的input,可以增加和删除和重新排序,数组元素生成的组件用index作为key的值,例如下图生成的ui展示: 上面例子中的input组件渲染的代码 ...

  3. 28.Linux-IIC驱动(详解)

    上一节 我们学习了: IIC接口下的24C02 驱动分析: http://www.cnblogs.com/lifexy/p/7793686.html 接下来本节, 学习Linux下如何利用linux下 ...

  4. Flutter 动画详解(一)

    本文主要介绍了动画的原理相关概念,对其他平台的动画做了一个简要的梳理,并简要的介绍了Flutter动画的一些知识. 1. 动画介绍 动画对于App来说,非常的重要.很多App,正是因为有了动画,所以才 ...

  5. (转).Net中自定义类作为Dictionary的key详解

    在定义数据结构时,Dictionary提供了快速查找数据的功能,另外Dictionary< TKey, TValue >属于key-value键值对数据结构,提供了泛型的灵活性,是数据结构 ...

  6. python标准库介绍——28 md5 模块详解

    ==md5 模块== ``md5`` (Message-Digest Algorithm 5)模块用于计算信息密文(信息摘要). ``md5`` 算法计算一个强壮的128位密文. 这意味着如果两个字符 ...

  7. (10)zabbix item key详解

    1. 灵活的参数 参数位置可用接收任意参数则是灵活的.例如vfs.fs.size[*],”*”星号可以使用任意的参数,例如:vfs.fs.size[/]vfs.fs.size[/opt] 2. Key ...

  8. Flutter TextField详解

    原文地址:https://www.jianshu.com/p/54419a143d70 实现TextField说简单也简单,说有坑,坑也不小,下面从易到难介绍一下使用 1.最简单的就是无参数调用构造方 ...

  9. 28 Corn表达式详解 (转自http://blog.csdn.net/claram/article/details/51785193)

    Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: Seconds Minutes Hours DayofMonth Month ...

  10. python标准库介绍——28 sha 模块详解

    ==sha 模块== ``sha`` 模块提供了计算信息摘要(密文)的另种方法, 如 [Example 2-39 #eg-2-39] 所示. 它与 ``md5`` 模块类似, 但生成的是 160 位签 ...

随机推荐

  1. Flask框架——请求扩展、flask中间件、蓝图、分析线程和协程

    文章目录 01 请求扩展 01 before_first_request :项目启动后第一次请求的时候执行 02 before_request:每次请求之前执行 03 after_request:每次 ...

  2. Vue源码学习(九):响应式前置:实现对象的依赖收集(dep和watcher)

    好家伙,这是目前为止最绕的一章,也是十分抽象的一章 由于实在太过抽象,我只能用一个不那么抽象的实例去说服我自己   完整代码已开源https://github.com/Fattiger4399/ana ...

  3. 手写商用Java虚拟机HotSpot,疯狂磨砺技术中

    在当前Java行业激烈竞争的形式下,唯有掌握技术,心中才不能慌.在多年前,我就开始苦练底层技术,但是眼看百遍也不如手过一遍,所以我打算把虚拟机的精华实现部分用手敲出来,这个过程注定不会轻松,但是心态不 ...

  4. 文心一言 VS 讯飞星火 VS chatgpt (119)-- 算法导论10.3 4题

    四.用go语言,我们往往希望双向链表的所有元素在存储器中保持紧凑,例如,在多数组表示中占用前m 个下标位置.(在页式虚拟存储的计算环境下,即为这种情况.)假设除指向链表本身的指针外没有其他指针指向该链 ...

  5. [Python急救站课程]绘制蜡笔小新图案

    可爱的蜡笔小新想要吗?画起来 import turtle as t '''设置''' t.setup(800, 500) # 创建画布并使其位于屏幕中心 t.pensize(2) # 画笔粗细 t.c ...

  6. 使用TS进行Vue-Router的Meta类型扩展

    目录 1.前言 2.解决 1.前言 使用Vue-Router时,会将一些字段信息附加到路由的Meta对象里面,比如图标icon,标题,权限等,如下: { path: '/billboard/board ...

  7. 文心一言 VS 讯飞星火 VS chatgpt (134)-- 算法导论11.2 6题

    六.用go语言,假设将n 个关键字存储到一个大小为 m 且通过链接法解决冲突的散列表中,同时已知每条链的长度,包括其中最长链的长度 L,请描述从散列表的所有关键字中均匀随机地选择某一元素并在 O(L· ...

  8. 放弃"Jenkins"的种种理由,期待更好赋能研发的持续交付平台

    Jenkins 很酷,但是不完美,有历史局限性造成的问题.本文仅从"如何更好给研发团队赋能的角度",剖析Jenkins, 探讨理想的持续交付平台, 不带货无广告- 不完美的Jenk ...

  9. JSX、TSX 整体理解

    可以少去理解一些不必要的概念,而多去思考为什么会有这样的东西,它解决了什么问题,或者它的运行机制是什么? JS JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web, ...

  10. 【公告】luogu blog (daiyulong20120222) 即将迁移!

    \[\huge\text{luogu blog (daiyulong20120222) 即将迁移到 cnblogs!}\\ \] \[\huge\color{blue}\text{https://ww ...