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
In the last chapter, because of the title, I didn’t introduce the content about GlobalKey. Today I will talk about GlobalKey.
GlobalKey is the only key in the entire application.
As we mentioned before, LocalKey is a local key, so when there is a hierarchy change:
Column(
children: [
Box(Colors.red, key: ValueKey(1)),
Center(child: Box(Colors.red, key: ValueKey(2))),
],
)
You can see that the red number has changed from 3 to 0, and the state is lost.
At this time, we will use globalKey. As we mentioned earlier, GlobalKey must be globally unique, so even if the widget changes from the position in the tree, it can still be found.
Use of GlobalKey
The use GlobalKey
should not be build
rebuilt every time GlobalKey
, it should be a long-lived object owned by State.
So we should first define a GlobalKey:
final GlobalKey _globalKey= GlobalKey();
Replace ValueKey with GlobalKey
This number is too small, I will change the code a little bit, enlarge the number, and change it to click on the number to perform the plus 1 operation. And change Column to Row:
Row(
children: [
Box(Colors.blue, key: ValueKey(1)),
Box(Colors.red, key: _globalKey),
],
)
Get the following effect:
It can be seen that the state of the widget using globalKey is perfectly preserved. The
previous state of using ValueKey is not retained because when the corresponding relationship is Widget Tree
made Element Tree
, the state is discarded because the type change cannot correspond.
GlobalKey method
We can use GlobalKey to find the corresponding widget, even state and other related things.
It can be seen that the global object provides several methods, and we mainly use the first three, which can be found through the globalKey BuildContext
, State
and Widget
.
Get the corresponding state
For example, we can use this globalKey
to find the number in the corresponding button, let's print it and have a look:
Corresponding code:
floatingActionButton: FloatingActionButton(
onPressed: () {
print((_globalKey.currentState as _BoxState).count);
},
child: Icon(Icons.wifi_protected_setup),
)
As you can see, I performed a type conversion above, because globalKey
any widget can be used, and flutter does not know which widget uses it before running, so we need to convert it to the corresponding type.
So if we want to change the value inside, can we do it?
Let's change onPress
the code a bit:
onPressed: () {
final state = _globalKey.currentState as _BoxState;
state.count++;
print(state.count);
state.setState(() {});
}
Remember, the setState operation must be performed to trigger the refresh of Ui, otherwise the value will be modified, but it is not reflected in the UI.
A better way to write it is
state.setState(() {
state.count++;
});
It is recommended to put the object that needs to be refreshed by setState into the braces {}, because in actual development, it is not necessary to refresh the UI every time an object changes. If the object that needs to be refreshed can be placed in setState according to the specification , When the requirements change and the code needs to be modified, when the setState is empty, we know that there is no need to refresh the UI, and we can delete the setState.
On the contrary, if it is written outside, when we delete the code of the object that needs to be refreshed, we don’t know whether this setState is still useful (after all, we may be developed by multiple people, or we may not remember the code we wrote before. ), resulting in an additional refresh operation.
Of course, the above operation is not recommended. Generally, its state is managed internally. If there are multiple widgets sharing it, it should be operated to write the variable to the outer layer 变量提示
.
Get the corresponding widget
We also saw just now, besides currentState
, it has some other things.
For example currentWidget
, of course, the type corresponding to our code has to be changed.
onPressed: () {
final widget = _globalKey.currentWidget as Box;
print(widget.color);
}
For example, here, because the widget is a Box, the type is converted to a Box. Through this currentWidget
, we can get the corresponding widget
attributes, such as the color here.
Get the corresponding context
Through currentContext
, you can get the corresponding context
, context
which actually refers to element
.
We introduced it in Chapter 2 element tree
, but didn’t go into details element
. Element
There are quite a lot of functions.
For example, I want to know the size and position of the corresponding component. This is actually difficult to obtain information.
final renderBox = _globalKey.currentContext!.findRenderObject() as RenderBox;
Here, we have currentContext!.findRenderObject
found the corresponding renderObject
, RenderObject
and there are still many types. Because what we have here Box
happens to be RenderBox
, so the type is converted to RenderBox
.
You can see renderBox
that there is a corresponding size
method, through which you can get the size of the corresponding widget.
If you want to get its location information, you can pass
renderBox.localToGlobal(Offset.zero);
To get the coordinate information from the upper left corner of the corresponding widget to the upper left corner of the screen.
Take a look at the printed information:
I/flutter ( 2158): Size(100.0, 100.0) //对应widget的尺寸
I/flutter ( 2158): Offset(100.0, 80.0) //对应widget的坐标
summary.
Finally, make a simple summary
This chapter mainly introduces two usages of globalKey. Both usages are to declare a globalKey first, and then pass this globalKey to the widget you want to put in.
The first usage ensures that the widget with the globalKey can change its position in the Widget Tree at will, and its state will not be lost.
The second usage is equivalent to exposing the widget through this key, and with it, you can getElementById
find its various things in a similar way:
- currentContext: You can find things related to various elements including renderBox
- currentWidget: You can get the properties of the widget
- currentState: You can get the variables in the state.