在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. 实战0-1,Java开发者也能看懂的大模型应用开发实践!!!

    前言 在前几天的文章<续写AI技术新篇,融汇工程化实践>中,我分享说在RAG领域,很多都是工程上的实践,做AI大模型应用的开发其实Java也能写,那么本文就一个Java开发者的立场,构建实 ...

  2. P8684 [蓝桥杯 2019 省 B] 灵能传输 题解

    P8684 [蓝桥杯 2019 省 B] 灵能传输 题解 Part 1 提示 题目传送门 欢迎大家指出错误并私信这个蒟蒻 欢迎大家在下方评论区写出自己的疑问(记得 @ 这个蒟蒻) Part 2 更新日 ...

  3. [ABC204E] Rush Hour 2 题解

    Rush Hour 2 题目大意 给定一张无向图,边带两个参数 \(c_i,d_i\),在 \(t\) 时间时经过第 \(i\) 条边所需的时间是 \(c_i+\lfloor\frac{d_i}{t+ ...

  4. Ansible自动化部署工具-组件及语法介绍

    大家好,我是蓝胖子,我认为自动化运维要做的事情就是把运维过程中的某些步骤流程化,代码化,这样在以后执行类似的操作的时候就可以解放双手了,让程序自动完成.避免出错,Ansible就是这方面非常好用的工具 ...

  5. Bug的解决

    关于使用Pandas的read_csv读取CSV文件. 用了三台Mac,在有header,同时有英文字符和中文字符的情况下,使用诸如datafile.loc[0:1 'column的名称']的方式无法 ...

  6. HTTP 和 HTTPS 之间除了安全性区别外,还有哪些区别

    HTTP 和 HTTPS 是两种常见的网络协议,它们都是用于在浏览器和服务器之间传输数据的.但是,它们之间也有一些重要的区别,这些区别涉及到数据的安全性.传输性能.使用成本和搜索排名等方面.本文将从以 ...

  7. vue+element-ui中引入编辑器

    wangeditor编辑器 1.执行:npm install  --save  wangeditor 2.在你需要调用编辑器的vue文件中引入 wangeditor: import E from 'w ...

  8. 现代统计分析软件Datainside在学生成绩分析中的应用

    Datainside(薪火数据)是一款非常常用的统计分析软件,广泛应用于学术研究和商业领域. 在学生成绩分析方面,Datainside提供了丰富的功能和工具,可以帮助教育机构和研究人员深入理解学生的学 ...

  9. 马云说的AI电商时代是什么

    这两天非常火的就是马老师说的,我们已经进入了AI的电商时代.相信电商时代大家很容易理解,换一个简单的方式来说就是网上购物. AI相信大家已经很熟悉了,就是人工智能.早在十年前其实已经有AI人工智能的概 ...

  10. 新建vue项目,并引入element ui和axios的步骤

    一.新建vue项目 (1)win+R进入命令行  使用cmd (2)切换到需要创建vue项目的盘符下    直接D:就能切换到D盘 (3)使用vue ui指令 进入图形化创建vue项目的界面(注意在创 ...