「这是我参加11月更文挑战的第28天,活动详情检查:2021最终一次更文挑战」。
- 咱们在快捷方式创立
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),
],
),
);
}
}