在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. 实训——基于大数据Hadoop平台的医疗平台项目实战

    文章目录 医疗平台项目描述 数据每列的含义 数据分析业务需求 架构图 成果图 环境搭建 非常感谢各位的认可,最近太多人找我问东问西,故在此进行说明一下: 首先这个是在Linux上基于Hadoop的搭建 ...

  2. $GNRMC

    $GNRMC 格式: $GNRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,&l ...

  3. MyBatis foreach循环批量修改数据时报错

    报错如下 org.springframework.jdbc.BadSqlGrammarException: ### Error updating database. Cause: java.sql.S ...

  4. 基于SpringBoot+Netty实现即时通讯(IM)功能

    简单记录一下实现的整体框架,具体细节在实际生产中再细化就可以了. 第一步 引入netty依赖 SpringBoot的其他必要的依赖像Mybatis.Lombok这些都是老生常谈了 就不在这里放了 &l ...

  5. mysqli操作

    1.使用mysqli_connect()函数,语法如下: mysqli 对象名=mysqli_connect(数据库服务名,用户名,密码,数据库名) 例:$conn=mysqli_connect('l ...

  6. Android Studio里导入制作好的图片后,直接报错,图片名下方出现红色波浪线

    症状:Android Studio里导入制作好的图片后,直接报错,图片名下方出现红色波浪线. 比如:bk_Image_BackGround,报红 解决办法:如:bk_Image_BackGround, ...

  7. RLChina理论三:强化学习基础

    强化学习基础 马尔可夫决策过程就是在,环境自发做出转变,是个随波逐流的过程,At是智能体的行动,在St环境状态下加入At动作,c才进入下个状态S(t+1),即环境有自己的变化,也加入了智能体的决策. ...

  8. JavaScript:用户代理检测:通过浏览器识别平台、操作系统等(Windows, Mac, iOS,iPad等)

    客户端检测经常用的方法:能力检测.怪癖检测和用户代理检测. 能力检测:在写代码前先检测浏览器的能力. 怪癖检测:实际上是浏览器现存的bug. 用户代理检测:通过检测用户代理字符串来识别浏览器. 一般优 ...

  9. Chromium VIZ工作流

    在 Chromium 中 viz 的核心逻辑运行在 GPU 进程中,负责接收其他进程产生的 viz::CompositorFrame(简称 CF),然后把这些 CF 进行合成,并将合成的结果最终渲染在 ...

  10. SharedArrayBuffer is not defined 问题的解决以及服务器https证书的配置

    问题 前端使用了ffmpeg压缩组件,在运行项目出现 SharedArrayBuffer is not defined的问题,使项目不能正常运行,经过网上查询,需要在response加入以下的head ...