The principle and use of Flutter Key (1) What happens without Key
The principle and use of Flutter Key (2) Correspondence between Widget and Element
The principle and use of Flutter Key (3) Three types of LocalKey
Principle and use of Flutter Key (4) Usage of GlobalKey
As we mentioned in the last chapter, if the same type in the same level Widget
is not passed to it Key
, sometimes Flutter will not be able to distinguish the correspondence between them, especially when the order between Widgets changes. At this time , we need to pass a key to it.
Types of keys
Key has two subclasses:
- LocalKey Local key, unique in the same level, can be understood as
同级唯一性
- GlobalKey Global key, must be unique in the entire App.
In terms of performance, if you don’t need to use GlobalKey, try not to use it. LocalKey will be much faster because it only compares the same level. As mentioned in the previous chapter, it will not be considered at the parent or child level. If you
violate If the above uniqueness principle is violated, an error will be reported at runtime, prompting you that the Key does not appear only once.
LocalKey
And LocalKey has 3 subclasses
- ValueKey
- ObjectKey
- UniqueKey
In fact, when all your Widgets are StatelessWidgets, you don’t need to use Key, and only when you use Statefuldiget can you use 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;
}
Its construction method is very simple, there is a value, the type is T, that is, you can pass whatever you want. Of course, because of the uniqueness principle, the value of Valuekey in the same level cannot be the same. You can see its method 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 is similar to ValueKey. Let’s mainly look at the difference. value
The type of ObjectKey has changed from T to Object, and operator
the method is different.
identical
When comparing whether it is equal or the same, it actually belongs to comparing references or whether pointers are equal, similar to Java. Compare memory addresses.
Let's create a slightly more complex class to see the actual difference between the two:
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;
}
Mainly look at operator
the method. When the ages are equal and the names are equal, it is judged to be equal.
At this time, if the code is like this:
Box(Colors.red, key: ValueKey(People('a', 18))),
Box(Colors.red, key: ValueKey(People('a', 18))),
After running,
Ah, as expected, an error was reported.
Then we try to change to ObjectKey:
This is because People('a', 18)
it is a new object from new (in dart, the new keyword can be omitted), flutter judges that the two are not the same object, because the corresponding ObjectKey is not equal. This is the main difference between
ObjectKey and ValueKey.
UniqueKey
class UniqueKey extends LocalKey {
UniqueKey();
@override
String toString() => '[#${shortHash(this)}]';
}
As the name suggests, UniqueKey
it is a unique Key, which means it is only equal to itself. Therefore UniqueKey()
, the UniqueKey()
sum is not equal.
It can be seen that after changing to UniqueKey, hot reload is performed and the state is lost. Because of Key
the change, the new UniqueKey is not equal to the old one. Therefore, there is no way to preserve the state.
So the question is, what is the use of this thing?
In fact, 丢失状态
it is a usage of it, which is generally used in animation effects.
In addition, it is not needed value
. When you don’t want to pass a value, as I 起名头疼
often have problems, when you need a key, what should the value pass? Value, I have to think about it for a while, maybe I still can’t think about it, so I simply don’t pass it on, and you can use UniqueKey at this time.
Then there is another problem, it will lose its state every time, which is not what we want, what should we do?
Define UniqueKey outside the build, such as
final keyRed = UniqueKey();
final keyBlue = UniqueKey();
Because there are two new keys from the beginning, keyRed is not changed when used, and our goal is achieved.
GlobalKey
Ok, let's talk about GlobalKey next, because of the title, we will talk about it in the next chapter.