1. 什么是key
您可以使用key来控制框架将在widget重建时与哪些其他widget匹配。默认情况下,框架根据它们的runtimeType和它们的显示顺序来匹配。使用key时,框架要求两个widget具有相同的key和runtimeType。
- Widget 更新机制
下面来来看Widget的源码。
@immutable
abstract class Widget extends DiagnosticableTree {
const Widget({
this.key });
final Key key;
···
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
}
Widget 只是一个配置且无法修改,而 Element 才是真正被使用的对象,并可以修改。当新的 Widget 到来时将会调用 canUpdate 方法,来确定这个 Element是否需要更新。返回true时可以更新对element索引
canUpdate 对两个(新老) Widget 的 runtimeType 和 key 进行比较,从而判断出当前的 Element 是否需要更新
If the widgets have no key (their key is null), then they are considered a match if they have the same type, even if their children are completely different.
那么设么时候用key呢?
2. key的使用
实例
- statelessWidget 实现两个颜色块交换
class StatelessContainer extends StatelessWidget {
final Color randomCol = getRandomColor();
@override
Widget build(BuildContext context) {
return Container(
width: 100,
height: 100,
color: randomCol,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({
Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Widget> widgets;
//初始化加载资源
@override
void initState() {
super.initState();
widgets = [
StatelessContainer(),
StatelessContainer()];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: widgets,
),
),
floatingActionButton: FloatingActionButton(
onPressed: switchWidget