Flutter Key的原理和使用 (一) 沒有Key會發生什麼

__white發表於2021-08-27

這是我參與8月更文挑戰的27天,活動詳情檢視:8月更文挑戰

在flutter中,幾乎每個widget都有一個Key,但是我們使用的時候一般不會傳Key , 那麼這個Key,它到底是幹什麼用的呢? 幾乎每個widget都有,但我們又很少用到它. 那到底什麼時候才需要用呢?

接下來,我們看一下,在需要Key的時候不用key,會發生什麼情況.

先舉個常見的例子:

Column(
  children: [
    Container(width: 100, height: 100,color: Colors.red),
    Container(width: 100, height: 100,color: Colors.blue),
  ]
),
複製程式碼

如果有上面一段程式碼,那麼會顯示兩個方塊,如圖:

image.png

如果把兩個Container調換位置,那麼UI上,兩個方塊也會換位置.這個沒什麼說的,很容易理解. 那如果是兩個稍微複雜的widget呢?

現在建立一個新的Wdiget:

class Box extends StatefulWidget {
  final Color color;

  const Box(this.color, {Key? key}) : super(key: key);

  @override
  _BoxState createState() => _BoxState();
}

class _BoxState extends State<Box> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Container(
        width: 100,
        height: 100,
        color: widget.color,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('$count', style: TextStyle(color: Colors.white)),
            IconButton(
              onPressed: () {
                setState(() {
                  count++;
                });
              },
              icon: Icon(Icons.add),
            )
          ],
        ));
  }
}
複製程式碼

這個Widget內部包含一個count,由自己管理它的狀態,並且有一個方法,可以改變這個值. 程式碼如下:

Column(
  children: [
    Box(Colors.red),
    Box(Colors.blue),
  ],
)
複製程式碼

現在用這個Widget替代上面的Container, 然後分別改變它們的值:

image.png

然後我們把兩個widget互換位置,看看之後的效果:

image.png

可以看到,它的顏色雖然換了,但是數字卻沒有互換,似乎不是我們期望的效果.

我們再嘗試改變一下程式碼

Column(
  children: [
    Box(Colors.red),
    Box(Colors.blue),
    Box(Colors.red),
  ],
)
複製程式碼

image.png

然後我們把第一個box,也就是紅色的widget去掉,hotreload一下, 會是什麼樣呢?

image.png

很神奇,紅色的確實消失了,但是按理說應該第一個去掉, 而藍色的2和紅色的3留下,然而卻留下了前兩個,並且數值還是第一個和第二個.

看起來,Flutter已經分不清誰是誰了,可是在我們看來,這裡並沒有複雜的邏輯.

那我們如果換成3個紅色的box呢? 把程式碼改成這樣:

Column(
  children: [
    Box(Colors.red),
    Box(Colors.red),
    Box(Colors.red),
  ],
)
複製程式碼

然後我們再刪掉第一個,程式碼就變成了:

Column(
  children: [
    Box(Colors.red),
    Box(Colors.red),
  ],
)
複製程式碼

如果不是自己親手刪除的,根本不知道是哪個不見了.只知道是少了一個.

如果我們依然像之前一樣,去調換順序呢? UI沒有改變, 可是調換之後程式碼並沒有變化,這麼看 似乎UI不變又不奇怪了. 程式碼都沒有變化,你指望UI有什麼變化呢?

好像找到了一點靈感, 是不是說明Flutter不能靠顏色來辨別是哪個widget,或者說顏色不能作為widget的唯一標識. 此時我們需要一個uuid來區分不同的widget, 而這 就是key的作用了.

我們如果給widget分別傳入不同的key, 就相當於各自有了一個id, 如果這3個id不同,那麼flutter也就不會混淆它們了.

Flutter有幾種不同的key,我會在後面為大家介紹. 之前定義box元件的時候,已經定義了一個key的引數, 此時我們分別傳入不同的key

Box(Colors.red,key: ValueKey(1)),
Box(Colors.red,key: ValueKey(2)),
Box(Colors.red,key: ValueKey(3)),
複製程式碼

因為有了key,flutter也就能區分它們了, 現在我們無論是調換還是刪除其中的widget, flutter的變化就都會朝著我們預期的方向發展了.

在實際開發中,我們也會遇到不同widget混淆的問題,一般情況下, 加一個ValueKey就可以解決了.

至於有什麼情況加ValueKey不能解決,我們後面也會介紹到.

相關文章