The principle and use of Flutter Key (3) Three types of LocalKey

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

The principle and use of Flutter Key (5) An example that requires a key: a Listview that can be dragged to change the order

As we mentioned in the last chapter, if the same type in the same level Widgetis 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. valueThe type of ObjectKey has changed from T to Object, and operatorthe method is different.
identicalWhen 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 operatorthe 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,

image.png

Ah, as expected, an error was reported.
Then we try to change to ObjectKey:

11123123.gif

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, UniqueKeyit is a unique Key, which means it is only equal to itself. Therefore UniqueKey(), the UniqueKey()sum is not equal.

aas.gif
It can be seen that after changing to UniqueKey, hot reload is performed and the state is lost. Because of Keythe 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.

Guess you like

Origin blog.csdn.net/u011272795/article/details/120082930