在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. Python面试题——网络与并发编程

    1.python的底层网络交互模块有哪些? socket, urllib,urllib3 , requests, grab, pycurl 2.简述OSI七层协议. OSI七层协议是一个用于计算机或通 ...

  2. NW排错

    fist date VM备份失败时: NW server上(linux): > nsradmin >p type : nsr recover > cd /nsr/logs >n ...

  3. Unity - EditorWindow 折叠树显示(IMGUI)

    仅适用于2018之前的版本,有UIElements或者UIWidgets的最好用新的 基本实现 树节点 public interface ITreeNode { ITreeNode Parent { ...

  4. 在不知带头节点地址的情况下删除和插入一个p指针指向的节点总结

    在不知带头节点地址的情况下删除和插入一个p指针指向的节点总结 (p指向的不是第一个,也不是最后一个)A->B->C *p->B 插入(在p结点之前插入q) 解析: 直接往p前插入q, ...

  5. HTML5的重要内容-1

    HTML学习笔记-1 (一):first-child和:first-of-type :first-child第一个元素 :first-of-type第一个某种类型元素 (二):only-child和: ...

  6. UIKit Inside: frame bounds position anchorPoint center

    iOS 中UIView的属性:frame.bounds.center以及CALayer的属性:position.anchorPoint与视图的位置与大小相关,理解这些属性是进行 iOS 视图编码的基础 ...

  7. RLHF · PBRL | 发现部分 D4RL tasks 不适合做 offline reward learning 的 benchmark

    论文题目:Benchmarks and Algorithms for Offline Preference-Based Reward Learning,TMLR 20230103 发表. open r ...

  8. (Good topic)贪心+二分查找:最长上升子序列(3.14 leetcode每日打卡)

    给定一个无序的整数数组,找到其中最长上升子序列的长度. 示例: 输入: [10,9,2,5,3,7,101,18]输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4. 说明 ...

  9. Kubernetes Gateway API 攻略:解锁集群流量服务新维度!

    Kubernetes Gateway API 刚刚 GA,旨在改进将集群服务暴露给外部的过程.这其中包括一套更标准.更强大的 API资源,用于管理已暴露的服务.在这篇文章中,我将介绍 Gateway ...

  10. Node.js精进(12)——ElasticSearch

    ElasticSearch(简称 ES)是一款基于 Lucene 的分布式.可扩展.RESTful 风格的全文检索和数据分析引擎,擅长实时处理 PB 级别的数据. 一.基本概念 1)Lucene Lu ...