0


Flutter:key的作用原理(LocalKey ,GlobalKey)

第一段代码实现的内容:创建了3个块,随机3个颜色,每次点击按钮时,把第一个块删除

  1. import'dart:math';import'package:flutter/material.dart';import'package:flutter_one/demo.dart';voidmain(){runApp(constApp());}classAppextendsStatelessWidget{constApp({Key? key}):super(key: key);
  2. @override
  3. Widget build(BuildContext context){returnconstMaterialApp(
  4. home:KeyDemo(),);}}classKeyDemoextendsStatefulWidget{constKeyDemo({Key? key}):super(key: key);
  5. @override
  6. State<KeyDemo>createState()=>_KeyDemoState();}class_KeyDemoStateextendsState<KeyDemo>{// 生成三个无状态的块
  7. List<Widget> items =[StlItem('1'),StlItem('2'),StlItem('3')];
  8. @override
  9. Widget build(BuildContext context){returnScaffold(
  10. appBar:AppBar(
  11. title:constText('KeyDemo'),
  12. centerTitle:true,),
  13. body:Row(
  14. mainAxisAlignment: MainAxisAlignment.center,
  15. children: items,),
  16. floatingActionButton:FloatingActionButton(
  17. child:Icon(Icons.add),
  18. onPressed:(){setState((){
  19. items.removeAt(0);// 点击按钮把第一个删除});}),);}}

先调用无状态的

  1. StatelessWidget

,当删除发生时看看效果

  1. classStlItemextendsStatelessWidget{
  2. final String title;StlItem(this.title,{Key? key}):super(key: key);// 随机的颜色
  3. final color = Color.fromRGBO(Random().nextInt(256),Random().nextInt(256),Random().nextInt(256),1.0);
  4. @override
  5. Widget build(BuildContext context){returnContainer(
  6. width:100,
  7. height:100,
  8. child:Text(title),
  9. color: color,);}}

发生删除时:
在这里插入图片描述
删除后
在这里插入图片描述
总结发现,如果是无状态的

  1. StatelessWidget

即使不传key:

  1. StlItem(this.title,{Key? key}) : super(key: key);

也能正常删除。

下面看下有状态的

  1. StatelessWidget

,不传key会出现什么BUG

  1. // 第一段代码中:生成三个有状态的块
  2. List<Widget> items =[StfulItem('1'),StfulItem('2'),StfulItem('3')];// 有状态classStfulItemextendsStatefulWidget{
  3. final String title;StfulItem(this.title,{Key? key}):super(key: key);
  4. @override
  5. State<StfulItem>createState()=>_StfulItemState();}class_StfulItemStateextendsState<StfulItem>{// 随机的颜色
  6. final color = Color.fromRGBO(Random().nextInt(256),Random().nextInt(256),Random().nextInt(256),1.0);
  7. @override
  8. Widget build(BuildContext context){returnContainer(
  9. width:100,
  10. height:100,
  11. child:Text(widget.title),
  12. color: color,);}}

删除前
在这里插入图片描述
删除后
在这里插入图片描述
发现问题了:我删除的是第一条数据,发现

  1. 文字1

正常删除,但是颜色怎么是把

  1. 颜色3

给删除了呢??

源码中,

  1. StatelessWidget

  1. StatefulWidget

都继承

  1. Widget
  1. abstract class StatefulWidget extends Widget{}

而在

  1. Widget

中有这样一个方法,Flutter的增量渲染就是通过

  1. canUpdate

来判断哪里需要更新数据。

  1. static bool canUpdate(Widget oldWidget, Widget newWidget) {
  2. return oldWidget.runtimeType == newWidget.runtimeType
  3. && oldWidget.key == newWidget.key;
  4. }

Flutter中的3棵树中,Widget树和Element树

每创建一个

  1. Widget

,都会有对应的

  1. Element

在这里插入图片描述
当删除第一个

  1. Widget

  1. Element

就会调用

  1. canUpdate

更新数据,

  1. Element

是按顺序判断,它会拿

  1. Element111

和删除后的

  1. Widget222

进行对比

  1. oldWidget.runtimeType == newWidget.runtimeType

旧的部件类型和新的部件类型是一样的,

  1. oldWidget.key == newWidget.key;

旧的没有传key和新的也没传key,结果那就是

  1. true

,增量渲染发现可以复用,

  1. Element111

就指向了

  1. Widget222

最后对比到

  1. Element333

,发现

  1. Widget

树中已经没有了,

  1. Element333

就被删除了。

那么颜色为什么会错了,因为颜色是保存在

  1. State

中,

  1. State

是保存在

  1. Element

中,所以最后一个颜色

  1. canUpdate

时被删除了。

在这里插入图片描述

加上key之后解决这个BUG

  1. List<Widget> items =[StfulItem('1',key:constValueKey('1'),),StfulItem('2',key:constValueKey('2'),),StfulItem('3',key:constValueKey('3'),)];

key的原理

  1. Key本身是一个抽象类,有一个工厂构造方法,创建ValueKey
  2. 直接子类主要有:LocalKey GlobalKey
  3. GlobalKey:帮助我们访问某个Widget的信息
  4. LocalKey :它用来区别哪个Element保留,哪个Element要删除
  5. ValueKey 以值作为参数(数字、字符串)
  6. ObjectKey:以对象作为参数
  7. UniqueKey:创建唯一标识

GlobalKey使用

  1. import'package:flutter/material.dart';classGlobalKeyDemoextendsStatelessWidget{// 定义:GlobalKey<拿谁的数据> 变量 = GlobalKey();
  2. final GlobalKey<_childPageState> _globalKey =GlobalKey();GlobalKeyDemo({Key? key}):super(key: key);
  3. @override
  4. Widget build(BuildContext context){returnScaffold(
  5. appBar:AppBar(
  6. title:constText('GlobalKeyDemo'),),
  7. body:childPage(
  8. key: _globalKey,),
  9. floatingActionButton:FloatingActionButton(onPressed:(){// _globalKey 就能访问到 _childPageState 中的属性,进行修改
  10. _globalKey.currentState!.setState((){
  11. _globalKey.currentState!.data ='hello word';
  12. _globalKey.currentState!.count++;});},
  13. child:constIcon(Icons.add),),);}}classchildPageextendsStatefulWidget{constchildPage({Key? key}):super(key: key);
  14. @override
  15. State<childPage>createState()=>_childPageState();}class_childPageStateextendsState<childPage>{
  16. int count =0;
  17. String data ='heelo';
  18. @override
  19. Widget build(BuildContext context){returnColumn(
  20. children:[Text(count.toString()),Text(data),],);}}

除了定义

  1. GlobalKey

外,还可以使用

  1. InheritedWidget

数据共享。


本文转载自: https://blog.csdn.net/qq_40745143/article/details/143812543
版权归原作者 sunly_ 所有, 如有侵权,请联系我们删除。

“Flutter:key的作用原理(LocalKey ,GlobalKey)”的评论:

还没有评论