This is the 13th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

The principle of the Key

static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
  }
Copy the code

As shown in Figure 1, when we generate a Widget tree, we also generate an Element tree, with widgets corresponding to elements. But when we remove Widget1 we call Element’s canUpdate method, which determines whether the old Widget has the same runtimeType and key as the new Widget. When we do not use key, they are equal by default, as shown in Figure 2, and Element1 compares oldWidget.runtimeType == newWidget.runtimeType, Because Element1 used to point to the same type as Widget2, Widget2 will reuse Element1, and Widget3 will reuse Element2, in turn, and remove Element3 when it doesn’t point to it. So the Key can be used to bind the Widget to determine whether canUpdate executes.

  • KeyIs itself an abstract class with a factory procedure constructorValueKey().
  • The direct subclasses mainly include:LocalKeyGlobalKey.
  • LocalKeyIt’s the heart of the incremental algorithmElementTo keep, whichElementWant to delete. The following is aLocalKeyThree subclasses of.
    • ValueKey: Takes a value as an argument (number, string)
    • ObjectKey: Takes an object as a parameter
    • UniqueKey: Creates a unique identifier
  • GlobalKeyAnswer to a certainWidgetorStateorElement.

The use of GlobalKey

class GlobalKeyDemo extends StatelessWidget { final GlobalKey<_ChildPageState> _globalKey = GlobalKey(); GlobalKeyDemo({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('GlobalKeyDemo'), ), body: ChildPage(key: _globalKey,), floatingActionButton: FloatingActionButton( onPressed: () { // _globalKey.currentContext // _globalKey.currentWidget _globalKey.currentState? .setState(() { _globalKey.currentState? .data = '666'; _globalKey.currentState? .count++; }); }, child: const Icon(Icons.add), ), ); } } class ChildPage extends StatefulWidget { const ChildPage({Key? key}) : super(key: key); @override _ChildPageState createState() => _ChildPageState(); } class _ChildPageState extends State<ChildPage> { int count = 0; String data = 'hello'; @override Widget build(BuildContext context) { return Center( child: Column( children: [ Text(count.toString()), Text(data) ], ), ); }}Copy the code

As shown in the example, when the onPressed closure in FloatingActionButton is executed we want to change the count and data values in _ChildPageState, We can define _globalKey = GlobalKey() in GlobalKeyDemo, passing _globalKey as an argument when initializing ChildPage. CurrentContext, _GlobalKey. currentWidget, and _GlobalKey. currentState. Here we get _ChildPageState with _GlobalKey. currentState, modify the data and count properties, and call setState. I feel that GlobalKey in Flutter is similar to the tag property of UIView in iOS. The corresponding UIView control can be obtained by tag.