第四百零五回 关于MediaQuery的优化


我们在上一章回中介绍了"如何获取AppBar的高度"相关的内容,本章回中将介绍 关于MediaQuery的优化.闲话休提,让我们一起Talk Flutter吧。

在这里插入图片描述

1. 问题描述

我们在前面章回中介绍获取屏幕参数时使用过MediaQuery类,主要通过它来获取MediaQueryData对象,然后从MediaQueryData对象中获取屏幕相关的参数。比如常用的屏幕长度和宽度,不过在使用时如果遇到键盘弹出或者隐藏时会引起Scaffold进行重绘(rebuild),而且是多次重绘,这种重绘显然不合理,它会导致不必要的性能开销,本章回中将介绍如何优化这种不合理的重绘。

2. 优化方法

明白我们遇到的问题后,我们介绍如何去解决这个问题,我们提供了两种解决方法,在接下来的小节中将介绍这两种方法。

2.1 缩小范围

我可以在使用MediaQuery的地方嵌套一个Build组件,这样可以让重绘只发生在Build组件内部,进而不影响页面中其它的组件。这种做法相当是缩小了重绘范围。

2.2 替代方法

我们还可以使用MediaQuery.sizeof()代替原来的方法,不过这种办法有一定的局限性,比如viewInsetOf方法就没有效果。它仍然会进行重绘。我推测它需要计算键盘高度,因此才去重绘。不过只是推测而已,真实的原因还需要查看源代码后才能明白。

3. 示例代码

 Widget build(BuildContext context) {
    // double screenWidth = MediaQuery.of(context).size.width;
    // double screenHeight = MediaQuery.of(context).size.height;

    ///使用下面的方法代替上面的方法,可以减少页面重绘
    double screenWidth = MediaQuery.sizeOf(context).width;
    double screenHeight = MediaQuery.sizeOf(context).height;
    debugPrint("build running");
    ///键盘高度,没有键盘弹出时为0
    // debugPrint("keyboard 1: ${MediaQuery.of(context).viewInsets.bottom}");
    ///这个方法不会减少页面重绘,可见只对sizeof有效果。
    // debugPrint("keyboard 1: ${MediaQuery.viewInsetsOf(context).bottom}");
    ///底部安全区域高度,没有时为0
    // debugPrint("keyboard 2: ${MediaQuery.of(context).viewPadding.bottom}");
    ///没有实际意义
    // debugPrint("keyboard 3: ${MediaQuery.of(context).viewInsets.top}");
    ///顶部状态栏的高度
    // debugPrint("keyboard 4: ${MediaQuery.of(context).viewPadding.top}");

    return Scaffold(
     appBar: AppBar(
       title: const Text("Example of Scaffold Overlay"),
     ),
      body: Stack(
        children: [
          Positioned(
            top: 400,
            left: 0,
            ///嵌套一层builder就不会引起页面重绘
            child: Builder(builder: (context) {
              double y = MediaQuery.of(context).size.height;
              debugPrint("build running of builder");
              return Text("check rebuilding value: ${y.toString()}");
            }),
          ),
          ///键盘自动弹出时会导到MediaQuery进行页面重绘,有两种解决方法:更换接口,嵌套builder
          const Positioned(
            top: 450,
            left: 0,
            width: 300,
            height: 56,
            child: TextField(),
          ),
        ],
      ),
    );
  }

上面的示例代码中大量使用了MediaQuery类,在页面中包含一个输入框,当我们点击输入框时会自动弹出键盘,此时可以看到代码中添加的日志出现在了运行结果中,这表明页面发生了生绘,具体点讲就是build方法在运行,而且会运行多次,输入完成后,点击键盘上的确认键,键盘会自动隐藏,此时也会发生重绘。

我们使用上一小节介绍的两种优化方法后,再次在输入框中输入内容,此时,页面不会发生重绘。我在这里就不演示具体的运行结果了,建议大家自己动手去实践。

4. 内容总结

最后,我们对本章回的内容做一个全面的总结:

  • 页面中使用MediaQuery类后,当键盘自动弹出和隐藏时会引起页面重绘;
  • 使用Build组件来缩小重绘范围,这样可以避免页面发生重绘;
  • 使用MediaQuery中的其它方法可以避免重绘,不过不是所有方法都有效果;

看官们,与"关于MediaQuery的优化"相关的内容就介绍到这里,欢迎大家在评论区交流与讨论!

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

talk_8

真诚赞赏,手有余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值