Principle and use of Flutter Key (4) Usage of GlobalKey

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

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))),
  ],
)

12a.gif

You can see that the red number has changed from 3 to 0, and the state is lost.

12a.gif
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.

12a.gif

Use of GlobalKey

The use GlobalKeyshould not be buildrebuilt 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:

asaed1.gif

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 Treemade 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.

image.png

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, Stateand Widget.

Get the corresponding state

For example, we can use this globalKeyto find the number in the corresponding button, let's print it and have a look:

asda.gif

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 globalKeyany 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 onPressthe 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 widgetattributes, such as the color here.

Get the corresponding context

Through currentContext, you can get the corresponding context, contextwhich actually refers to element.

We introduced it in Chapter 2 element tree, but didn’t go into details element. ElementThere 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!.findRenderObjectfound the corresponding renderObject, RenderObjectand there are still many types. Because what we have here Boxhappens to be RenderBox, so the type is converted to RenderBox.

image.png

You can see renderBoxthat there is a corresponding sizemethod, 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 getElementByIdfind 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.

Guess you like

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