Flutter 中 key 的原理及作用Key 的原理 如图 1 所示,当我们生成一个 Widget 树的时候也会对应生
Key 的原理


static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
如图 1 所示,当我们生成一个 Widget 树的时候也会对应生成 Element 树,Widget 与 Element 一一对应。但是当我们移除 Widget1 的时候会调用 Element 的 canUpdate 方法,canUpdate 方法中会判断旧的 Widget 与新的 Widget 的 runtimeType 是否相等,且 key 是否相等。当我们不使用 key 时候,就会默认它们相等,就会如图 2 所示,Element1 就会比较 oldWidget.runtimeType == newWidget.runtimeType,因为 Element1 曾经指向的类型与 Widget2 类型相同所以 Widget2 就会复用 Element1,同理 Widget3 就会复用 Element2,依次比较,当 Element3 没有指向的时候就会被移除。所以 Key 的作用可以用来跟 Widget 做绑定,判断 canUpdate 是否执行。
Key本身是一个抽象类,有一个工厂程构造方法ValueKey()。- 直接子类主要有:
LocalKey跟GlobalKey。LocalKey是增量算法的核心,决定哪个Element要保留,哪个Element要删除。以下是LocalKey的三个子类。
ValueKey:以值作为参数(数字、字符串)ObjectKey:以对象作为参数UniqueKey:创建唯一标识GlobalKey对应某一个Widget或者State或者Element。
GlobalKey 的使用
class GlobalKeyDemo extends StatelessWidget {
final GlobalKey<_ChildPageState> _globalKey = GlobalKey();
GlobalKeyDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('GlobalKeyDemo'),
),
body: ChildPage(key: _globalKey,),
floatingActionButton: FloatingActionButton(
onPressed: () {
// _globalKey.currentContext
// _globalKey.currentWidget
_globalKey.currentState?.setState(() {
_globalKey.currentState?.data = '666';
_globalKey.currentState?.count++;
});
},
child: const Icon(Icons.add),
),
);
}
}
class ChildPage extends StatefulWidget {
const ChildPage({Key? key}) : super(key: key);
@override
_ChildPageState createState() => _ChildPageState();
}
class _ChildPageState extends State<ChildPage> {
int count = 0;
String data = 'hello';
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
Text(count.toString()),
Text(data)
],
),
);
}
}
如案例所示,当 FloatingActionButton 中 onPressed 闭包函数执行的时候我们想修改 _ChildPageState 中 count 及 data 的值,我们可以在 GlobalKeyDemo 中定义 _globalKey = GlobalKey(),在初始化 ChildPage 的时候把 _globalKey 作为参数传递。这时候我们可以通过 _globalKey.currentContext、_globalKey.currentWidget、_globalKey.currentState 获取我们想拿到的部件,这里我们通过 _globalKey.currentState就能获取到 _ChildPageState 修改 data 及 count 属性,并调用 setState 方法。个人感受 Flutter 中的 GlobalKey 有点类似 iOS 中 UIView 的 tag 属性,可以通过 tag 来获取到对应的 UIView 控件。
转载自:https://juejin.cn/post/7035650818845966372