GlobalKey 介绍

在整个应用程序中是唯一的Key GlobalKey可以唯一标识元素,GlobalKey提供了对这些元素相关联的访问,比如BuildContext。对于StatefulWidgets,GlobalKey也提供对State的访问。

GlobalKey使用的注意事项

GlobalKey不应该在build方法中初始化,否则会每次build都重建GlobalKey,更好的办法是让State对象拥有GlobalKey对象,然后在 State.initState 的方法中初始化GlobalKey。

通过使用GlobalKey来实现局部刷新,优化性能

例如在一个高清图片查看器里面,想要有一个点击图片显示/隐藏退出按钮的功能,如果此时调用setState对整个UI数进行重绘性能开销非常大,包含高清图片的重绘。这时把退出按钮单独封装,然后使用GlobalKey来控制退出按钮的状态,此时只会重绘关闭按钮,而不会重绘整个界面。

  • 退出按钮代码如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import 'package:flutter/material.dart';

class AnimationCloseButton extends StatefulWidget {
  final VoidCallback? onTap;
  final bool initShow;

  const AnimationCloseButton({Key? key, this.onTap, this.initShow = true})
      : super(key: key);

  @override
  State<AnimationCloseButton> createState() => AnimationCloseButtonState();
}

class AnimationCloseButtonState extends State<AnimationCloseButton> {
  // 是否显示本widiget
  bool showWidget = true;
  // 是否需要自动隐藏,判断是否点击过
  bool needAutoHide = true;

  @override
  void initState() {
    super.initState();
    showWidget = widget.initShow;
    Future.delayed(const Duration(seconds: 3), () {
      if (mounted && needAutoHide && showWidget) {
        setState(() {
          showWidget = false;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedOpacity(
        opacity: showWidget ? 1.0 : 0.0,
        duration: const Duration(milliseconds: 250),
        child: GestureDetector(
          onTap: () => widget.onTap?.call(),
          child: Container(
            width: 50,
            height: 50,
            alignment: Alignment.center,
            padding: const EdgeInsets.all(3),
            decoration: BoxDecoration(
              color: Colors.black54,
              borderRadius: const BorderRadius.all(Radius.circular(28)),
              border: Border.all(width: 0, style: BorderStyle.none),
            ),
            child: const Icon(Icons.close, color: Colors.white),
          ),
        ));
  }

  void changingDisplayState() {
    if (needAutoHide) {
      needAutoHide = false;
    }
    if (mounted) {
      setState(() {
        showWidget = !showWidget;
      });
    }
  }
}
  • 调用代码如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import 'package:flutter/material.dart';

import 'global_key_close_widget.dart';

class GlobalKeyDemo extends StatefulWidget {
  const GlobalKeyDemo({Key? key}) : super(key: key);

  @override
  State<GlobalKeyDemo> createState() => _GlobalKeyDemoState();
}

class _GlobalKeyDemoState extends State<GlobalKeyDemo> {
  // GlobalKey 用于控制 关闭按钮的显示或者隐藏
  GlobalKey<AnimationCloseButtonState>? closeButtonController;

  @override
  void initState() {
    super.initState();
    // 注意GlobalKey不能再build方法中初始化
    closeButtonController = GlobalKey<AnimationCloseButtonState>();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
          child: Center(
        child: Column(
          children: [
            AnimationCloseButton(
              key: closeButtonController,
              onTap: () => print('AnimationCloseButton is Clicked!'),
            ),
            const SizedBox(
              height: 20,
            ),
            GestureDetector(
              onTap: () =>
                  closeButtonController?.currentState!.changingDisplayState(),
              child: Container(
                width: 200,
                height: 100,
                alignment: Alignment.center,
                color: Colors.grey,
                child: const Text(
                  '点击显示或隐藏关闭按钮',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ],
        ),
      )),
    );
  }
}

效果

globalkey-demo