Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

这篇具有很好参考价值的文章主要介绍了Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关于 MediaQuery 我们介绍过不少,比如在之前的《MediaQuery 和 build 优化你不知道的秘密》里就介绍过,要慎重在 Scaffold 之外使用 MediaQuery.of(context) ,这是因为 MediaQuery.ofBuildContext 的绑定可能会导致一些不必要的性能开销,例如键盘弹起时,会导致相关的 MediaQuery.of(context) 绑定的页面出现重构。

比如下面这个例子,我们在 MyHomePage 里使用了 MediaQuery.of(context).size 并打印输出,然后跳转到 EditPage 页面,弹出键盘 ,这时候会发生什么情况?

class MyHomePage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    print("######### MyHomePage ${MediaQuery.of(context).size}");
    return Scaffold(
      body: Container(
        alignment: Alignment.center,
        child: InkWell(
          onTap: () {
            Navigator.of(context).push(CupertinoPageRoute(builder: (context) {
              return EditPage();
            }));
          },
          child: new Text(
            "Click",
            style: TextStyle(fontSize: 50),
          ),
        ),
      ),
    );
  }
}

class EditPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: new Text("ControllerDemoPage"),
      ),
      extendBody: true,
      body: Column(
        children: [
          new Spacer(),
          new Container(
            margin: EdgeInsets.all(10),
            child: new Center(
              child: new TextField(),
            ),
          ),
          new Spacer(),
        ],
      ),
    );
  }
}

如下图 log 所示 , 可以看到在键盘弹起来的过程,因为 bottom 发生改变,所以 MediaQueryData 发生了改变,从而导致上一级的 MyHomePage 虽然不可见,但是在键盘弹起的过程里也被不断 build 。

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

虽然在之前的小技巧里我们介绍了解决方式,但是 3.10 开始有更优雅的做法,同时也更方便我们自足控制更细的颗粒度地去管理 InheritedWidget 里的绑定关系,那就是使用 InheritedModel

MediaQuery

在 3.10 里 MediaQuery 增加了需要针对特定参数的 ****of 方式,例如 MediaQuery.platformBrightnessOf(context); ,这些方法对应在 _MediaQueryAspect 里都有一个枚举类型,而在 Flutter Framework 里,这些参数的调用都修改成了新的 ****of 类型方法。

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

例如一开始的例子,只需要将 MediaQuery.of(context).size 修改为 MediaQuery.sizeOf(context) ,那么跳转到 EditPage 页面,弹出键盘 ,在键盘弹起来的过程中不会再导致 MyHomePage rebuild 输出 log。

而之所以会这样的原因,其实是因为这些 MediaQuery.******Of(context); 内部调用的是 InheritedModel.inheritFrom 实现。

是的,3.10 开始 MediaQuery 继承从 InheritedWidget 变成 InheritedModel ,而 InheritedModelinheritFrom 方法可以让开发者可以通过 aspect 来决定数据改变时是否调用对应更新

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

小技巧一:3.10 现在可以通过将 MediaQuery.of 获取参数的方式替换成 MediaQuery.******Of(context); 来减少不必要的 rebuild

InheritedModel

使用 InheritedModel 只需要继承它就可以,之后需要重点关注的是 updateShouldNotifyDependent 方法,它用于决定应该什么时候 rebuild

如下图所示是 MediaQuery 的实现,在 updateShouldNotifyDependent 里我们可以通过 dependencies 里的类型来进行区分,比如调用时是通过 InheritedModel.inheritFrom<MediaQuery>(context, aspect: _MediaQueryAspect.size) 输入,那么判断时就会进入到 _MediaQueryAspect. size 这个 case

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

如果此时 size 参数发生了改变,就返回 true ,从而产生 rebuild,反之返回放 false,这就是 InheritedModel 可以根据绑定具体变量来更新页面的原因。

当然这里你不一定要传枚举,你喜欢的话传 String 也可以,具体可以根据你的爱好来设定。

那为什么 InheritedModelinheritFrom 方法可以达到这样的效果?

我们简单看一下 inheritFrom 的源码实现,如下图所示:

  • 在没有 aspect 的时候直接调用 dependOnInheritedWidgetOfExactType() 那就是和之前普通的 of(context) 没什么区别
  • 在有 aspect 的时候,会先通过 _findModels 找到对应的 InheritedElement ,然后调用 dependOnInheritedElement() 绑定

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

可能这时候你有些疑问,不要急慢慢来,我们先看 dependOnInheritedWidgetOfExactType()dependOnInheritedElement() , 其实 dependOnInheritedWidgetOfExactType() 内部也是调用 dependOnInheritedElement() 来完成绑定,那么这里前后的区别是什么?

如果你仔细看,这里的区别在于 dependOnInheritedElement() 多使用了 aspect ,对应到 MediaQuery 里就是如 _MediaQueryAspect.size 这个 aspect ,这样在后续 updateShouldNotifyDependent 时就会被用上。

如下图所示是 InheritedModelInheritedModelElement ,可以看到 inheritFrom 传入的 aspect 会变成 dependencies ,而这个 dependencies 就是我们在 updateShouldNotifyDependent 里用来判断的类型依据。

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

最后,在 notifyDependent 方法里可以看到,只有 updateShouldNotifyDependent 返回 true 时,才会调用 didChangeDependencies 去更新。

所以 inheritFrom 的特殊之处在于:当存在 aspect 时,该 aspect 会变成 dependencies 集合,然后通过 updateShouldNotifyDependent 来决定是否触发更新

至于 _findModels 方法其实你无需纠结,虽然它是传入一个 List,但是一般情况下你只会获取到一个。什么时候会可能有多个,就是你 override 了 InheritedModelisSupportedAspect 方法,并且会根据 aspect 条件有不同判断返回时可能会有多个。

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

例如都是继承 InheritedModel ,但是 isSupportedAspect 可以根据条件来决定你这个实例是否支持 Aspect 绑定。

  
  bool isSupportedAspect(Object aspect) {
    return aspects == null || aspects!.contains(aspect);
  }

另外 _findModels 里用的是 getElementForInheritedWidgetOfExactType(),它和 dependOnInheritedWidgetOfExactType() 的区别就是前者会注册依赖关系,而后者不会,所以 _findModels 顾名思义只是找出符合条件的 InheritedModel

Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel

最后

最后总结一下,今天的小技巧其实很简单,就是更新你的 MediaQuery.of 到对应参数的 MediaQuery.*****of 从而提升应用性能,并且了解到 InheritedModel 的实现逻辑和自定义支持,从而学会优化你现在的 InheritedWidget 的使用。

如果你还有什么问题,欢迎留言评论交流。文章来源地址https://www.toymoban.com/news/detail-478941.html

到了这里,关于Flutter 小技巧之 3.10 全新的 MediaQuery 优化与 InheritedModel的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Flutter调优--深入探究MediaQuery引起界面Rebuild的原因及解决办法

    我们可以通过 MediaQuery.of(context) 方法获取到一些设备和系统的相关信息,比如状态栏的高度、当前是否是黑暗模式等等,使用起来相当方便,但是也要注意可能引起的页面rebuild问题。本文会介我们可以通过 MediaQuery.of(context) 方法获取到一些设备和系统的相关信息,比如状态栏

    2024年02月06日
    浏览(37)
  • Flutter必备技能:轻松掌握本地存储与数据库优化技巧!

    正因为有网络,App拥有与外界进行信息交换的通道,也因此具备了更新数据的能力。不过,经过交换后的数据通常都保存在内存中,而应用一旦运行结束,内存就会被释放,这些数据也就随之消失了。 因此,我们需要把这些更新后的数据以一定的形式,通过一定的载体保存起

    2024年02月09日
    浏览(69)
  • 10 个优化技巧,减少 Docker 镜像大小

    Docker 是一种容器引擎,可以在容器内运行一段代码。Docker 镜像是在任何地方运行您的应用程序而无需担心应用程序依赖性的方式。 要构建镜像,docker 使用一个名为 Dockerfile 的文件。Dockerfile 是一个包含许多指令(RUN、COPY、EXPOSE 等)的文件。成功执行这些命令后,docker 将创

    2023年04月17日
    浏览(45)
  • 新品发布 | Cloudpods 3.10版本上线!

    Cloudpods 是一个开源的 Golang 实现的云原生的多云和混合云融合平台。 Cloudpods 不仅可以管理本地的虚拟机和物理机资源,还可以管理其他公有云和私有云平台的资源。 Cloudpods 由北京云联壹云技术有限公司主导开发,并于 2019 年 9 月于 Github 开源。Cloudpods 采用核心开源模式,其

    2024年02月03日
    浏览(32)
  • 百度搜索排名的提升,就靠这10个优化技巧!

    随着互联网的快速发展,网站排名已经成为了企业竞争的一个重要指标。其中,百度搜索排名的提升更是众多企业都非常关注的问题。因此,在这篇文章中,我将为大家介绍10个优化技巧,以帮助企业提升百度搜索排名。   1.优化 优化是SEO优化的一个重要部分。

    2024年02月07日
    浏览(93)
  • SEO优化新手必须掌握的10个技巧和工具

    随着互联网的不断发展,SEO(搜索引擎优化)已成为网站拓展和推广的重要手段之一。对于新手而言,学习SEO的基础知识和技巧是至关重要的。在本文中,我将分享SEO优化新手必须掌握的10个技巧和工具。 1.研究 是SEO优化的重中之重,因为它们直接影响着您的排

    2024年02月07日
    浏览(64)
  • python下载安装教程(Python 3.10版本)

    今天换了新的电脑,需要重新安装python和PyCharm,就简单的写个教程吧~ 1、进入Python官网 官网地址:https://www.python.org 2、点击【Downloads】展开后点击【Windows】跳转到下载python版本页面,选择\\\"Stable Releases\\\"稳定版本,我下载的是Python 3.10.10版本,所以找到【Python 3.10.10-Feb.8,2023】

    2024年02月10日
    浏览(69)
  • Win10技巧:16个系统优化设置,全面提升电脑性能

    目录 1. 注册你的Microsoft账户 2. 夜间模式 3. 关闭登录验证(办公机慎用) 4. 文件内容预览 5. 组件升级 6. 剪贴板增强 7. Caps Lock声音提醒 8. 自启动清理 9. 安装PowerToys 10. 文件历史记录 11. 动态锁 12. 就近共享 13. 搜索范围 14. “勒索”防护

    2024年04月10日
    浏览(65)
  • python3.8,3.9,3.10,3.11特性比较

    最近计划将python2迁移到python3,由于本人学习时用的3.7版本,所以仅作大于3.7版本的比较。 文档地址:python3.8 作用:避免重复调用,使代码更加简洁。PS:别当GO写,它不支持声明并赋值变量 作用: 新增了一个函数形参语法 / 用来指明某些函数形参必须使用仅限位置而非关键

    2024年02月05日
    浏览(62)
  • Linux 3.10 GCC版本太低升级到5.2.0

    某次升级内核,执行make menuconfig报当前版本太低,现场版本为4.8.5,需要升级到5.1.0版本以上,查看官网后,决定升级到5.20版本。注:GCC依赖于gmp 4.2+, mpfr 2.4+和mpc 0.8+,报错如下: 官方说明:https://gcc.gnu.org/install/index.html;https://gcc.gnu.org/;https://ftp.gnu.org/gnu/gcc/gcc-5.2.0/

    2024年02月14日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包