What is the Key
In the official line:
Key is used as an identifier for the Widget, Element, and SemanticsNode, and is only used to update the status of widgets with the same Widget ->key.
Key subclasses include LocalKey and GlobalKey.
LocalKey
Take a look at the definition of LocalKey:
abstract class LocalKey extends Key {
const LocalKey() : super.empty();
}
Copy the code
LocalKey defines the initialization function, which defaults to null.
LocalKey subclass containing ValueKey/ObjectKey/UniqueKey, as shown in figure:
ValueKey
ValueKey, as the name implies, compares values
Let’s look at the key function
@override bool operator ==(Object other) { if (other.runtimeType ! = runtimeType) return false; return other is ValueKey<T> && other.value == value; }Copy the code
It is also easy to use when we want the system to determine whether we can refresh based on the key we have given it.
TextField(
key: ValueKey('value1'),
),
TextField(
key: ValueKey('value2'),),Copy the code
When we swap the order, the TextField values are swapped, so our key takes the value away.
TextField(
key: ValueKey('value2'),
),
TextField(
key: ValueKey('value1'),),Copy the code
What if we use another class to pass values? We’re passing in class Student as value.
class Student {
final String name;
Student(this.name);
@override
int get hashCode => name.hashCode;
}
TextField(
key: ObjectKey(Student('Lao wang')),
),
TextField(
key: ObjectKey(Student('Lao wang'))),Copy the code
No error is reported after refresh, normal use.
Let’s take a look at this after Student overrides the == operator, so let’s change the Student code a little bit
class Student {
final String name;
Student(this.name);
@override
int get hashCode => name.hashCode;
@override
bool operator= = (Object other) =>
identical(this, other) ||
other is Student &&
runtimeType == other.runtimeType &&
name == other.name;
}
Copy the code
Then hot reload, error
If multiple keyed nodes exist as children of another node, they must have unique keys.
Copy the code
Student == (Key = Value); Student == (Key = Value);
ObjectKey
How does this key compare objects? Let’s look at the source code;
@override
bool operator= = (Object other) {
if(other.runtimeType ! = runtimeType)return false;
return other is ObjectKey
&& identical(other.value, value);
}
Copy the code
The official display of comparison type, when the type is inconsistent, it is judged as not through one object, if the other is also ObjectKey, then judge whether the address is the same, only the same address is judged as the same object.
Test data;
class Student {
final String name;
Student(this.name);
@override
int get hashCode => name.hashCode;
@override
bool operator= = (Object other) =>
identical(this, other) ||
other is Student &&
runtimeType == other.runtimeType &&
name == other.name;
}
TextField(
key: ObjectKey(Student('Lao wang')),
),
TextField(
key: ObjectKey(Student('Lao wang'))),Copy the code
No error is reported after the interface is refreshed.
ObjectKey has been modified slightly
_student = Student('Lao wang');
TextField(
key: ObjectKey(_student),
),
TextField(
key: ObjectKey(_student),
),
Copy the code
Error after refresh, same key exists.
If multiple keyed nodes exist as children of another node, they must have unique keys.
Copy the code
UniqueKey
Generating a different value every time, when we need a new value every time we refresh, is exactly what this is all about.
Each time we refresh, we generate a new color and fade in and out.
AnimatedSwitcher(
duration: Duration(milliseconds: 1000),
child: Container(
key: UniqueKey(),
height: 100,
width: 100,
color: Colors.primaries[count % Colors.primaries.length],
),
)
Copy the code
Effect:
GlobalKey & GlobalObjectKey
As a key for global use, we can usually use GlobalKey to refresh other widgets when across widgets.
The criteria for GlobalObjectKey and ObjectKey equality are consistent. GlobalObjectKey extends GlobalKey, specifying the State to inherit via GlobalKey
>, and the class that implements the StatefulWidget interface. You can then get the currentState with globalkey.currentstate, and then call state.setstate ((){}) to complete marking the current widget as dirty, and refresh the current widget in the next frame.
example
Click the button to refresh the background color of the widget.
GlobalKey _key = GlobalKey();
_Container(_key),
OutlineButton(
child: Text('Global Key Refresh'),
onPressed: () {
_key.currentState.setState(() {});
},
Copy the code
Click globalKey to refresh the local widget, and click the lower right corner to refresh the entire page. As you can see, only the bottom widget changes color when part of the page is refreshed, while the entire page is refreshed.
Effect:
reference
- Sample code base
- The official source
The article summary
Dart asynchrony and multithreading
Insight into state management –ScopeModel
Learn more about Flutter management –Redux
Detailed explanation of Flutter (iii. In-depth understanding of state management –Provider)
4. Deeper understanding of state management –BLoC
A detailed explanation of Flutter
1, Learn about the Stream
7. Understand the principle of drawing deeply
Detailed explanation of Flutter
Project recommend
- A cool loading animation library
- Flutter100 + component usage examples
- Flutter entry to advanced ebook