Flutter入门进阶之旅(二十三)Flutter Key

引言:
在Flutter中,Key是一个非常重要的概念,它可以帮助我们优化性能,避免重建问题,并确保Widget正确地进行更新。本文将对Flutter Key进行详细解析,并介绍如何在实际开发中灵活应用。

一. 什么是Key?

Key是Flutter中的一个抽象类,它用于标识Widget。每个Flutter Widget都可以使用Key作为唯一标识符来识别自己,也可以用于将新的Widget与旧的Widget进行比较。Key本身没有任何具体实现,但它的子类有多种类型可供选择,如ValueKey、ObjectKey等。

具体分类如下:

1.1Key的类型在Flutter中,Key主要有以下几种类型:

  • ValueKey:这是最常用的Key类型,它将一个值赋予给Key。当两个ValueKey的值相同时,Flutter框架会认为这两个Key是相同的。

  • ObjectKey:与ValueKey类似,但是ObjectKey使用的是对象的引用。

  • UniqueKey:每次创建都会生成一个唯一的Key。

  • GlobalKey:这是一个全局唯一的Key,可以在整个应用中引用
    mage.png

  • LocalKey

LocalKey 直接继承至 Key,它应用于拥有相同父 Element 的小部件进行比较的情况,也就是上述例子中,有一个多子 Widget 中需要对它的子 widget 进行移动处理,这时候你应该使用Localkey。它也是我们日常用到的比较多的key。

Localkey 派生出了许多子类 key:

  • ValueKey : ValueKey(‘String’)
  • ObjectKey : ObjectKey(Object)
  • UniqueKey : UniqueKey()
  • Valuekey 又派生出了 PageStorageKey : PageStorageKey(‘value’)

注:如果是statelessWidget,那么就没必要使用key了,因为每一帧widget都会重建;而statefulWidget由于使用了state,state当中通常会缓存很多需要在UI上展示的变量,它不会时常重建,所以就需要使用key来强制改变。

扫描二维码关注公众号,回复: 16645211 查看本文章
  • ValueKey

可以传入任何对象,比较的时候会对比它的内容是否一致。

  
  bool operator ==(Object other) {
    
    
    if (other.runtimeType != runtimeType)
      return false;
    return other is ValueKey<T>
        && other.value == value;
  }
  • ObjectKey

可以传入任何参数,比较的时候会比较它的指针是否一致,即是否为同一个对象。

  
  bool operator ==(Object other) {
    
    
    if (other.runtimeType != runtimeType)
      return false;
    return other is ObjectKey
        && identical(other.value, value);
  }
  • UniqueKey

不需要传任何参数,每次刷新都会生成一个新的值,通常用于动画的过渡当中。比如:

         AnimatedSwitcher(
              duration: const Duration(seconds: 1),
              child: Text("no keyrrths", key: UniqueKey()),
            )

每次改变文字时,假如不传uniqueKey,就不会有动画的渐变效果,而如果传了UniqueKey,则会有渐变动画效果。因为不传uniqueKey时,每次都只会认为text的widget发生了变化,只会将text的widget给替换为新的widget,而element还是同一个不会变化,所以会认为UI没有发生变化,因此不会改变;而如果传了uniqueKey时,每次widget比较时都会因为自身的key不一致而被认为是不同的widget,导致会重建element和renderObject,前后两个UI不一致,此时就会发生动画效果。

  • GlobalKey

全局变量,顾名思义,整个应用程序里都是唯一的,所以同一个globalKey只能作用在一个widget上。可以通过globalKey拿到所对应的state和element或者widget,用以改变state的状态或者变量值,以及刷新UI。不过不推荐这样做,一般推荐通过控制外面的变量来刷新UI。


        floatingActionButton: FloatingActionButton(
          onPressed: (){
    
    
            var state = (_globalKey as BoxState);
            state.count++;
            state.setState(() {
    
    
            });
          },
          child: const Icon(Icons.add),
        ),

二. Key的作用

2.1 唯一标识符

Key的主要作用是唯一标识Widget。当Widget结构发生变化时,Flutter会根据Key来识别旧Widget和新Widget的不同,以确定是否需要进行重建。如果没有Key,Flutter将无法区分不同的Widget,会将它们全部重建,导致性能下降。

2.2 优化性能

通过Key,Flutter可以高效地更新Widget树中的部分子树,而不是重新构建整个Widget树。这样可以避免不必要的重建,提高性能。

2.3 避免重建问题

在某些情况下,我们希望保持Widget的状态不变,即使Widget的位置发生了改变。Key可以帮助我们解决这个问题,通过给Widget添加唯一的Key,确保在更新Widget树时能够正确地保留原来的状态,而不是将其重置为默认值。

三. Key的使用示例

3.1 构建列表

在构建列表时,我们经常会用到ListView.builder,此时我们需要使用IndexedWidgetBuilder作为itemBuilder参数。为了确保列表项的正确显示和更新,我们需要给每个列表项添加唯一的Key,通常使用ValueKey或ObjectKey。

List<String> items = ["item1", "item2", "item3"];

ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    
    
    return ListTile(
      key: ValueKey(items[index]), // 或者使用ObjectKey(items[index])
      title: Text(items[index]),
    );
  },
);

3.2 更新Widget

当我们需要更新一个已经存在的Widget时,如果Widget的类型发生了变化,Flutter会认为这是一个不同的Widget,而不仅仅是属性的变化,从而会重新构建整个部分子树。为了避免这种重建,我们可以在更新时使用相同的Key。

ValueKey("myKey") // 使用相同Key更新Widget

四. Key的使用规范

4.1 唯一性

每个Widget应该有一个唯一的Key,这样Flutter才能正确地识别它们的不同。如果出现相同的Key,Flutter将会报错并抛出异常。

4.2 稳定性

Key应该是稳定的,不应该随着Widget的属性变化而变化。如果Key随着Widget的属性改变而改变,那么Flutter将会认为这是一个不同的Widget,导致重建。

4.3 可维护性

Key应该是可读性好的、具有描述性的字符串或其他类型。这可以帮助我们快速定位问题,以及在需要时进行调试。

总结

Key在Flutter中是一个非常重要的概念,它可以帮助我们更好地管理和更新Widget。理解和掌握Key的使用,可以帮助更好地优化性能、避免重建问题,并确保Widget正确地进行更新。

猜你喜欢

转载自blog.csdn.net/xieluoxixi/article/details/121626028
key