Flutter中key的作用

文章来源于Flutter Widgets 101 Ep. 4,感兴趣的同学可以直接看视频,更便于理解。

首先,我们要明白Key的作用,Keys preserve state when widgets move around in your widget tree. They can be used to preserve the user's scroll location, or keeping state when modifying a collection. (当组件在组件树中移动时使用Key可以保持组件之前的状态,比如在用户滑动时或者集合改变时),这是一个抽象的定义,大家尽量理解原文,在后面的例子中可以很好的理解。

什么时候使用Key?

我们参照视频,写下了如下Demo,当点击FloatingActionButton时,交换两个Widget的位置。(你可以下载项目,运行一下,会更便于理解)

image.png

  1. 当我们使用Stateless Widget时,widget可以正常的移动。swap_color_1.dart
  2. 当我们把Widget改为Stateful时,交换出现了问题。swap_color_2.dart
  3. 当我们为Stateful加入Key之后,程序又能正常的执行swap_color_3.dart

从Demo中我们可以看出,当使用Stateless Widget时,我们并不需要使用key,当使用Stateful Widget时,集合内有数据移动和改变并且需要展示到界面时才需要key。

Key应该用到哪?

首先我们来搞懂上面,为什么swap_color_2会出问题,要明白这个问题,我们需要明白Flutter的渲染策略。

我们在构建Flutter的UI时是以Widget的形式『拼接』出来的,组件树作为UI每一个组件都对应一个元素(原文中是Slot),从而形成了『元素树』(Element Tree),元素树的内容非常简单,只包含了组件的类型和子元素的引用(Type),你可以把元素树当做Flutter App中的骨架(skeleton),它只展现了App的结构,并不包含其他具体的信息。

当我们交换组件树中的元素时,组件确实进行了交换,但是元素树却不一定。Flutter会先遍历(walk)整个元素树,从Row上的主元素,到主元素的子元素,查看整体的结构是否发生了变化,当然,它检查的只能是元素的Type和Key,在给出的例子中,当我们不设置Key时,元素树对比Type,发现Type并没有发生变化,而Flutter却是用元素树和元素对应的状态(可用或者不可用),来决定这个元素是否应该显示出来,所以在界面中并没有发生改变,但是当我们加入Key之后,对比的对象多了一个,并且是和之前不一样的,Flutter察觉到之后,立即改变了元素的状态,让它变为『无用状态』(deactivate),当遍历完之后,Flutter会浏览(look through)这些不匹配的元素(non-matched children)通过相应的引用为之找到对应的组件。当所有的元素都匹配完成之后,Flutter会刷新界面,展现出我们预想的。


Widget Tree and Element Tree

那么Key到底应该用到哪呢?
我们再来一个例子,swap_color_4,我们把色块用Padding包装一下。运行之后会发现,色块并没有交换,而是以随机的形式在变换颜色。为什么呢?

Padding Stateful

结合我们上面的理论,我们分析一下这次的Widget Tree 和 Element Tree,当我们交换元素后,Flutter element-to-widget matching algorithm,(元素-组件匹配算法),开始进行对比,算法每次只对比一层,即Padding这一层。显然,Padding并没有发生本质的变化。
Padding Widget Tree

于是开始进行第二层对比,在对比时Flutter发现元素与组件的Key并不匹配,于是,把它设置成不可用状态,但是这里所使用的Key只是本地Key(Local Key),Flutter并不能找到另一层里面的Key(即另外一个Padding Widget中的Key)所以,Flutter就创建了一个新的Widget,而这个Widget的颜色就成了我们看到的『随机色』。


Stateful Widget Tree

通过上面的示例,我们能明显的看出,我们的Key要设置到组件树的 顶层,而这一层在改变时,才能复用或者更新状态。

用哪一种Key?

Flutter中有很多Key,但是总体分为两种 Local Key和Global Key两种。


Key UML

对于Key的研究还不是特别多,有时间再补一篇,上面的例子,因为没有数据,所以使用了UniqueKey,在真实的开发中,我们可以用Model中的id作为ObjectKey。

GlobalKey其实是对应于LocalKey,上面我们说Padding中的就是LocalKey,Global即可以在多个页面或者层级复用,比如两个页面也可也同时保持一个状态。

还处在学习Flutter状态,如有错误请您及时指正,谢谢。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容