/// Creates a key that delegates its [operator==] to the given value.
const ValueKey(this.value);
/// The value to which this key delegates its [operator==]
final T value;
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType)
return false;
return other is ValueKey && other.value == value;
}
/// Creates a key that uses [identical] on [value] for its [operator==].
const ObjectKey(this.value);
/// The object whose identity is used by this key's [operator==].
final Object? value;
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType)
return false;
return other is ObjectKey
&& identical(other.value, value);
}
@override
int get hashCode => hashValues(runtimeType, identityHashCode(value));
案例:建立一个稍微复杂的类以此查看二者的区别:
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;
}
class UniqueKey extends LocalKey {
/// Creates a key that is equal only to itself.
///
/// The key cannot be created with a const constructor because that implies
/// that all instantiated keys would be the same instance and therefore not
/// be unique.
/// ignore: prefer_const_constructors_in_immutables ,
///never use const for this class
UniqueKey();
@override
String toString() => '[#${shortHash(this)}]';
}
Flutter中Key的原理及使用 LocalKey (一)
发文时间:2022年03月22日 14:53:13 编辑:Aaron 标签:flutter key 1639
简述关于flutter中的Key和案例 - LocalKey。LocalKey下有3个子类 1:ValueKey、 2:ObjectKey、 3:UniqueKey、
前言
在Flutter 中一切皆 Widget,同一级中相同类型的Widget不给它传Key的话,Flutter有时候就会出现分不清它们之间的对应关系,尤其是Widget之间的顺序发生改变的时候,此时 我们就需要传个key给它 而 Widget 的构造方法中有个可选参数 Key。
Key的种类
在Flutter中key有两个子类分别为
1、 LocalKey 依官方的解释为局部键,在同一级的Widget中要唯一,可以理解为同级中的唯一级。
而LocalKey又有3个子类
1.1:ValueKey
1.2:ObjectKey
1.3:UniqueKey
2、GlobalKey 全局键,就是在整个APP中必须是唯一的。
关于LocalKey中的三个子类详解
1: ValueKey -案例
ValueKey源码
案例:假设在Column中存在三个不同颜色的TestBox按钮块,TestBox代码如下,内包含背景色和count以此来记录值。
如下图所示 案例中分别有红黄蓝 且对应的数字分别为 红=1, 黄=2,蓝=3
假设把红色1的Widget注释掉,然后hotreload一下,此时的ui会是怎样呢?
效果如下,如图所示 红色块确实已经消失了,按常理来说此时红色的确实要去掉 黄2和蓝3应该留下,但是此时的方块值已经发生了改变 由 红=1, 黄=2,蓝=3 改变为:黄=1,蓝=2,由此可以看出flutter已经分辨不出来谁是谁了,或者说颜色并不能当做是widget的唯一标识。
那么就需要类似于uuid来区分每一个widget的,这就是key的作用了,如果我们给每一个widget传入不同的key,就相当于每一个widget有各自的id标识,那么flutter就不会混淆它们的值了。
在同一级下的widget 因为有了key(ValueKey),flutter就可以区分,所以我们现在无论是删除还是调换widget的顺序他都可以按key对号入座对应的参数,而不会混淆。
提问: 在什么业务场景下可能会用到这个ValueKey呢 ?
答:假设在类似于购物车列表的场景下,每个商品明细都不一致,而你想对每个商品进行滑动排序或者删除操作,使用ValueKey将是不错的选择。
2: ObjectKey -案例
通过查看源码可得知 ObieckKey和ValueKey大同小区,主要的区别是value的类型从T变成了为Object,operator方法也不一样,identical对比是否是相等或者说相同的时候,它其实属于对比引用或者说指针是否相等即可。
案例:建立一个稍微复杂的类以此查看二者的区别:
测试 ValueKey的operator方法,当年龄相等并且姓名相等时,就判断是相等的,那么程序会是怎样
此时代码如果是这样的话:
果不其然,程序报错了,我们换成ObjectKey试试:
OK~ 完美运行
这就是因为People('Aaron', 18)是new出来的新对象(小提示:在Dart中,new关键字是可以被忽略的) flutter判断两者不是同一个对象,因为对应的ObjeckKey也不相等,这就是ObjectKey和ValueKey的主要区别。
3: UniqueKey -案例
UniqueKey源码
顾名思义,UniqueKey在flutter中是一个独一无二的Key,也就是说它只和自己相等,如若在build内定义 每次hotReload后就会丢失状态,因为新的Uniquekey和旧的是不一致的,所以就状态就无法保留,因此UniqueKey()和UniqueKey()是不相等的。期初学习到这个UniqueKey后,时常在想到底在什么场景下才用这个呢,自以为的感觉有些鸡肋... 但经过查阅后发现并不是(暴露了水平)
其实在flutter中丢失状态也是一种它的用法,一般可以在动画中使用到,另外UniqueKey不用传入value,当你不想传value但是又想让它丢失状态时就挺方便的,我个人是比较头疼起名的.. 时常和同事讲起 编程最难的不是代码而是如何起名 。
关于上述所提到的每次hotReload后UniqueKey()会丢失状态,假设我们又不想让它每次都会丢失状态的话,可以把UniqueKey定义到build的外部就好了,
因为程序一开始就new出来的两个Key,所以在使用的时候,key是没有改变的,也就达到了想要的效果。
知足常乐~
若无特殊说明,此文章为博主原创。
写稿不易,如需转载,请注明出处: https://www.aaroner.cn/art/24.html