Flutter-->何時(shí)需要使用到key蚤霞?


引言

key是控件構(gòu)造函數(shù)的一個(gè)可選參數(shù),key保存了控件的狀態(tài)义钉,我們可以利用key修改控件的狀態(tài)昧绣。

一個(gè)例子解釋何時(shí)使用key

其實(shí)大多數(shù)時(shí)候,我們是不需要關(guān)心key對(duì)捶闸,但是如果我們需要對(duì)處于某種狀態(tài)的相同類型的控件集合進(jìn)行添加夜畴,刪除或重新排序時(shí),我們就需要用到key了删壮。下面是一個(gè)何時(shí)需要key的簡(jiǎn)單例子贪绘。


上面例子展示的效果是,點(diǎn)擊右下角的切換央碟,可以對(duì)集合里的控件進(jìn)行位置切換税灌。
主頁面的代碼如下所示:

class _MyHomePageState extends State<MyHomePage> {
  List<Widget> widgets;

  @override
  void initState() {
    super.initState();
    widgets = [
      StatelessColorTile(),
      StatelessColorTile(),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
          child: Row(
        children: widgets,
      )),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          changePosition();
        },
        child: Text('交換'),
      ),
    );
  }

  changePosition() {
    setState(() {
      widgets.insert(1, widgets.removeAt(0));
    });
  }
}

StatelessColorTile控件

class StatelessColorTile extends StatelessWidget {
  final Color color = RandomColor().randomColor();
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: color,
    );
  }
}

上面代碼中我們可以看到顏色方塊是一個(gè)無狀態(tài)的控件。

接下來我們將無狀態(tài)的StatelessColorTile改成有狀態(tài)的StatefulColorTile,如下所示:

class StatefulColorTile extends StatefulWidget {
  StatefulColorTile({Key key}) : super(key: key);
  @override
  _StatefulColorTileState createState() => _StatefulColorTileState();
}

class _StatefulColorTileState extends State<StatefulColorTile> {
  final Color color = RandomColor().randomColor();
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: color,
    );
  }
}

主頁面發(fā)生改變的代碼:

  @override
  void initState() {
    super.initState();
    widgets = [
      StatefulColorContainer(),
      StatefulColorContainer(),
    ];
  }

改變成有狀態(tài)的方塊之后菱涤,我們點(diǎn)擊右下角的切換按鈕苞也,發(fā)現(xiàn)集合中的方塊位置不能進(jìn)行交換了,但是如果我們將有狀態(tài)的方塊添加一個(gè)key,集合中的方法位置就能進(jìn)行切換了粘秆,如下所示:

  @override
  void initState() {
    super.initState();
    widgets = [
      StatefulColorTile(
        key: UniqueKey(),
      ),
      StatefulColorTile(
        key: UniqueKey(),
      ),
    ];
  }

針對(duì)上面的實(shí)例我們接下來可以用圖解的方式了解key的運(yùn)作方式墩朦。

1. 當(dāng)方塊為無狀態(tài)的控件時(shí)
在Flutter中,對(duì)于每個(gè)控件翻擒,flutter都會(huì)構(gòu)建一個(gè)相應(yīng)的元素,而這個(gè)元素只會(huì)保存每個(gè)控件的類型牛哺,以及對(duì)子元素的引用信息陋气。我們上面例子的控件樹和對(duì)應(yīng)的元素樹,如圖1所示引润,

圖1

圖2
圖3
圖4

圖2:交換Row中的方塊控件的順序巩趁;
圖3:flutter會(huì)遍歷元素樹以查看骨架結(jié)構(gòu)是否相同,它以Row元素開頭淳附,然后移動(dòng)到其子元素议慰,元素樹檢查新的小部件是否與舊的小部件類型和key相同(但在這種情況下,方塊widget沒有key奴曙,因此flutter只檢查其類型)别凹,因?yàn)樾屡f方塊控件的類型是相同,所以元素會(huì)更新對(duì)新控件的引用洽糟;
圖4:就會(huì)達(dá)到預(yù)期的切換效果(Row對(duì)第二個(gè)子元素的檢查也是如此)炉菲。

2. 當(dāng)方塊為有狀態(tài)但無key的控件時(shí)

圖5
圖6
圖7

圖5:當(dāng)方塊為有狀態(tài)但無key的控件時(shí),我們發(fā)現(xiàn)顏色值存儲(chǔ)在對(duì)應(yīng)控件的元素中坤溃,而不是控件本身中拍霜。
圖6:交換Row中的方塊控件的順序
圖7:交換兩個(gè)方塊控件后,F(xiàn)lutter會(huì)遍歷元素樹薪介,因?yàn)榉綁K控件沒有key祠饺,所以Flutter只會(huì)檢查其類型,因?yàn)轭愋拖嗤栽馗聦?duì)新控件對(duì)引用道偷,但是由于兩個(gè)方塊對(duì)顏色是存儲(chǔ)在元素中的,所以只是兩個(gè)方塊控件發(fā)生了變化烂完,而其對(duì)應(yīng)的顏色并不會(huì)發(fā)生變化试疙。

3. 當(dāng)方塊為有狀態(tài)且有key的控件時(shí)

圖8

圖9
圖10
圖11
圖12
圖13
圖14

圖8:當(dāng)方塊為有狀態(tài)且有key的控件時(shí),我們發(fā)現(xiàn)元素中除了存儲(chǔ)控件的顏色值抠蚣,還存儲(chǔ)了控件的key值祝旷。
圖9:交換Row中的方塊控件的順序
圖10:交換兩個(gè)方塊控件后,會(huì)像上面說的一樣匹配,但是我們發(fā)現(xiàn)元素中的key和相應(yīng)方塊控件的key不匹配.
圖11:當(dāng)發(fā)現(xiàn)元素中的key和相應(yīng)方塊控件的key不匹配后怀跛,F(xiàn)lutter會(huì)停用這些元素距贷。
圖12:Flutter會(huì)從第一個(gè)不匹配的方塊控件,從元素樹中查找具有相應(yīng)key的元素吻谋,找到之后會(huì)更新其對(duì)應(yīng)方塊控件的引用忠蝗。
圖13:匹配完第一個(gè)方塊控件后,F(xiàn)Lutter會(huì)為第二個(gè)方塊控件做同樣的事情漓拾。
圖14:最后阁最,F(xiàn)lutter將會(huì)顯示我們預(yù)期的內(nèi)容,兩個(gè)方塊交換位置并更新其顏色骇两。

總結(jié)

通過上面例子我們可以學(xué)習(xí)到速种,如果我們需要修改集合中的控件的順序或數(shù)量,則我們應(yīng)該使用key低千。
參考資料:
When to Use Keys-Flutter Widgets 101 Ep.4

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末配阵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子示血,更是在濱河造成了極大的恐慌棋傍,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件难审,死亡現(xiàn)場(chǎng)離奇詭異瘫拣,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)剔宪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門拂铡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人葱绒,你說我怎么就攤上這事感帅。” “怎么了地淀?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵失球,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我帮毁,道長(zhǎng)实苞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任烈疚,我火速辦了婚禮黔牵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘爷肝。我一直安慰自己猾浦,他們只是感情好陆错,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著金赦,像睡著了一般音瓷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上夹抗,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天绳慎,我揣著相機(jī)與錄音,去河邊找鬼漠烧。 笑死杏愤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的已脓。 我是一名探鬼主播声邦,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼摆舟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起邓了,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤恨诱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后骗炉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體照宝,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年句葵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厕鹃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乍丈,死狀恐怖剂碴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情轻专,我是刑警寧澤忆矛,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站请垛,受9級(jí)特大地震影響催训,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宗收,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧顽冶,春花似錦宝当、人聲如沸审胚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽菲盾。三九已至,卻和暖如春各淀,著一層夾襖步出監(jiān)牢的瞬間懒鉴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工碎浇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留临谱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓奴璃,卻偏偏與公主長(zhǎng)得像悉默,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子苟穆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,089評(píng)論 1 32
  • 國(guó)慶后面兩天在家學(xué)習(xí)整理了一波flutter抄课,基本把能擼過能看到的代碼都過了一遍,此文篇幅較長(zhǎng)雳旅,建議保存(star...
    Nealyang閱讀 4,338評(píng)論 1 17
  • 本文主要介紹了Flutter布局相關(guān)的內(nèi)容跟磨,對(duì)相關(guān)知識(shí)點(diǎn)進(jìn)行了梳理,并從實(shí)際例子觸發(fā)攒盈,進(jìn)一步講解該如何去進(jìn)行布局抵拘。...
    Q吹個(gè)大氣球Q閱讀 9,714評(píng)論 6 51
  • 文章來源于Flutter Widgets 101 Ep. 4,感興趣的同學(xué)可以直接看視頻,更便于理解型豁。 首先僵蛛,我們...
    森碼閱讀 18,852評(píng)論 7 37
  • 本文對(duì)Flutter的29種布局控件進(jìn)行了總結(jié)分類,講解一些布局上的優(yōu)化策略迎变,以及面對(duì)具體的布局時(shí)充尉,如何去選擇控件...
    Q吹個(gè)大氣球Q閱讀 10,537評(píng)論 15 153