Flutter学习-30-Flutter的key
- 我们在快捷方式创建
stateless Widget
或者stateful Widget
时候会让我们创建一个key
,之前一直没有讲讲解,接下来 就探讨下。
1. 例子
我们创建一个listView
添加3个cell
,同时给他随机颜色,点击的时候移除第一个元素,
class _keyDemoState extends State<keyDemo>{
List<String> names = ['1111','2222','3333'];
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(),
body: ListView(
children: names.map((str) {
return listCell(name: str,);
}).toList(),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
names.removeAt(0);
setState(() {
});
},
tooltip: 'delete',
child: const Icon(Icons.delete),
),
)
);
}
}
cell的样式
class listCell extends StatelessWidget {
final String? name;
final Color bgcolor = Color.fromRGBO(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1) ;
listCell({Key? key,this.name,}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 44,
child: ListTile(
tileColor:bgcolor ,
title: Text(name!),
)
);
}
}
我们点击删除,移除了第一个元素,但是setState
后重新build
了,颜色重新随机了
这显然不是我们想要的样子。我们把cell换成statefulWidget
点击删除
发现数据发生了变化,但是颜色没有发生变化
,我们删除了最后一个的颜色和第一个的文字。
- 这是因为在删除第一条数据的时候,
Widget对应的Element
并没有改变; - 而
Element
中对应的State引用
也没有发生改变; - 在更新
Widget
的时候,Widget
使用了没有改变的Element
中的State
;
2. key的使用
我们给我们的statefulWidget
添加key
点击删除后,得到我们想要的效果
我们查看源码
当我们的 [runtimeType]
and [key]
没有发生变化的时候Element
就不更新,我们删除第一个widget
的时候,因为widget
的key
都是空而且[runtimeType]
也是一样的,所以直接使用之前的Element
,
我们使用随机key
的话
删除后
也验证了每次我们的key发生变化
后,Element
会强制刷新
,那么对应的State
也会重新创建
3. key的分类
key
是一个抽象类
,里面有个工厂构造函数
可以返回key
key有2个子类
LocalKey
和GlobalKey
3.1 LocalKey
LocalKey
主要分为3个子类
-
ValueKey
:- ValueKey是当我们以特定的值作为key时使用,比如一个字符串、数字等等
-
ObjectKey
:- 如果两个模型,他们的类型一样,使用type作为他们的key就不合适了
- 我们可以创建出一个模型对象,使用对象来作为key
-
UniqueKey
- 如果我们要确保key的唯一性,可以使用UniqueKey;
- 比如我们之前使用随机数来保证key的不同,这里我们就可以换成UniqueKey;
3.2 GlobalKey
可以帮助我们访问某个Widget的信息
,包括Widget
或State
或Element
等对象
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.currentState!.setState(() {
_globalKey.currentState!.data =
'old:' + _globalKey.currentState!.count.toString();
_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),
],
),
);
}
}
转载自:https://juejin.cn/post/7035930570056007716