Flutter Key的原理和使用(三) LocalKey的三种类型

Flutter Key的原理和使用(一) 没有Key会发生什么

Flutter Key的原理和使用(二) Widget 和 Element 的对应关系

Flutter Key的原理和使用(三) LocalKey的三种类型

Flutter Key的原理和使用(四) GlobalKey 的用法

Flutter Key的原理和使用(五) 需要key的实例:可拖动改变顺序的Listview

我们在上一章说到,同一级中相同类型的Widget不给它传Key的话,Flutter有时候就会出现分不清它们之间的对应关系,尤其是Widget之间的顺序发生改变的时候. 此时,我们就需要传个key给它.

Key的种类

Key有两个子类:

  • LocalKey 局部键,在同一级中要唯一,可以理解为同级唯一性
  • GlobalKey 全局键 , 在整个App中必须是唯一的.

从性能上来讲,如果不需要用到GlobalKey的话,尽量不用,LocalKey因为只对比同一级别,因此会快很多.上一章也说过,在父级或者子级是不会需考虑的.
如果违背了上述的唯一性原则,运行时会报错,提示你Key没有只出现一次.

LocalKey

而LocalKey又有3个子类

  • ValueKey
  • ObjectKey
  • UniqueKey

其实当你的Widget全都是StatelessWidget的时候,不需要用到Key,只有当使用Statefuldiget的时候才有可能用到key.

ValueKey

const ValueKey(this.value)

final T value;

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

它的构造方法很简单,有一个value,类型是T,也就是随便你想传什么都可以.当然因为唯一性原则,同级中Valukey的value是不能相同的.这个可以看它的operator方法.

ObjectKey

const ObjectKey(this.value);

final Object? value;

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

ObjectKey跟ValueKey大同小异,我们主要看一下区别,value的类型从T变成了Object,operator方法也不一样.
identical对比是否是相等或者说相同的时候,它其实属于对比引用或者说指针是否相等,类似于Java中对比内存地址.

我们创建一个稍微复杂一点的类看一下二者实际的区别:

class People{
  final String name;
  final int age;

  People(this.name, this.age);

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is People && runtimeType == other.runtimeType && name == other.name && age == other.age;

  @override
  int get hashCode => name.hashCode ^ age.hashCode;
}

主要看一下operator方法,当年龄相等并且姓名相等时,就判断是相等的.
此时如果代码是这样的话:

Box(Colors.red, key: ValueKey(People('a', 18))),
Box(Colors.red, key: ValueKey(People('a', 18))),

运行之后,

image.png

啊,果不其然,报错了.
然后我们换成ObjectKey试试:

11123123.gif

这就是因为People('a', 18)是new出来的新对象(在dart中,new关键字是可以被省略的),flutter判断二者不是同一个对象,因为对应的ObjectKey也不相等.
这就是ObjectKey跟ValueKey的主要区别.

UniqueKey

class UniqueKey extends LocalKey {
  UniqueKey();

  @override
  String toString() => '[#${shortHash(this)}]';
}

顾名思义,UniqueKey是一个独一无二的Key,也就是说它只和自己相等.因此UniqueKey()UniqueKey()是不相等的.

aas.gif
可以看到,换成UniqueKey之后,再进行hot reload,发现状态丢失了,因为Key变了, 新的UniqueKey和旧的是不相等的.所以state就没有办法保留下来.

那么问题来了, 这玩意到底有啥用?

其实,丢失状态就是它的一种用法,一般在动画效果中会用到.
另外就是它不需要value,当你不想传个value的时候,像我经常有起名头疼的毛病,需要key的时候,这个value该传什么值, 我得想一会,可能还想不好,索性不传了,此时可以使用UniqueKey.

那就又有个问题,它每次都会丢掉状态啊,不是我们希望的,怎么办?

把UniqueKey定义到build的外部,比如

final keyRed = UniqueKey();
final keyBlue = UniqueKey();

因为是一开始就new出来的两个Key,所以在使用的时候,keyRed是没有改变的,也就达到了我们的目的.

GlobalKey

ok,接下来说到GlobalKey , 因为标题的原因啊,我们下一章再讲它.

猜你喜欢

转载自blog.csdn.net/u011272795/article/details/120082930
今日推荐