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

news2024/12/24 10:05:47

关于 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 。

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

MediaQuery

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

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

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

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

小技巧一: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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最后

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

如果你还有什么问题,欢迎留言评论交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/610415.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue项目仿企业微信移动端(带聊天界面)

网上比较知名的网站或者软件&#xff0c;开源代码中都有仿其前端的。比如小米商城&#xff0c;京东商城&#xff0c;仿微信聊天页面诸如此类的。所以我潜意识觉得像那种知名公司或者软件。想找它的仿前端静态代码应该很好找。结果&#xff0c;当我想找仿企业微信移动端的前端静…

springboot+vue住房分配管理系统vue

本城镇保障性住房管理系统管理员&#xff0c;用户。管理员功能有个人中心&#xff0c;用户管理&#xff0c;房屋类型管理&#xff0c;房源信息管理&#xff0c;房源申请管理&#xff0c;住房分配管理&#xff0c;留言板管理&#xff0c;系统管理等。因而具有一定的实用性。 本…

c++11 标准模板(STL)(std::bitset)(四)

定义于头文件 <bitset> template< std::size_t N > class bitset; 类模板 bitset 表示一个 N 位的固定大小序列。可以用标准逻辑运算符操作位集&#xff0c;并将它与字符串和整数相互转换。 bitset 满足可复制构造 (CopyConstructible) 及可复制赋值 (CopyAssign…

华为OD机试真题 Java 实现【矩阵稀疏扫描】【2023 B卷 100分】,附详细解题思路

一、题目描述 如果矩阵中的许多系数都为零&#xff0c;那么该矩阵就是稀疏的。对稀疏现象有兴趣是因为它的开发可以带来巨大的计算节省&#xff0c;并且在许多大的实践中都会出现矩阵稀疏的问题。 给定一个矩阵&#xff0c;现在需要逐行和逐列地扫描矩阵&#xff0c;如果某一…

使用阿里云免费Serverless函数计算产品资源安装 Stable Diffusion

喜欢用 Stable Diffusion 的小伙伴注意了&#xff01;上一篇介绍了使用谷歌的 Colab 免费资源来安装这个画图神器。 但因为资源是免费的&#xff0c;高峰时期有可能会被谷歌断掉服务的连接&#xff0c;像周末这种使用高峰&#xff0c;GPU 的资源得不到保证。 没关系&#xff0c…

WPF开发txt阅读器:需求分析和文件读写

文章目录 需求分析读取文本文件保存文本文件 需求分析 尽管现在比较主流的阅读格式已经是epub, modi之类的&#xff0c;但txt的使用范围要远比前两者广泛&#xff0c;所以做一个txt阅读器还是有必要的。 但是对于书籍阅读而言&#xff0c;纯文本不包含目录信息&#xff0c;这…

chatgpt赋能python:Python奇数偶数判断:从基础语法到优化运行

Python奇数偶数判断&#xff1a;从基础语法到优化运行 Python是一门简单易学的编程语言&#xff0c;并且在科学计算、数据处理和人工智能等领域都有广泛的应用。在Python中&#xff0c;判断一个数是奇数还是偶数是一个基础问题&#xff0c;本文将介绍Python中奇数偶数的判断方…

事务与项目跟踪软件Jira

本文软件应网友 不长到一百四誓不改名 要求折腾&#xff1b; 什么是 Jira &#xff1f; Jira 是由 Atlassian 开发的跟踪和管理任务的软件开发工具&#xff0c;您可以将它用于敏捷和瀑布项目管理&#xff0c;以跟踪错误、功能和其他工作项。您还可以将 JIRA 配置为与许多服务管…

Leetcode之二分查找

1. 二分查找 二分查找的前提条件是&#xff1a;有序数组。 二分查找的递归实现&#xff1a; class Solution: def search_recur(self,nums:List[int],low:int,high:int,target:int):if low > high:return -1mid low (high - low) // 2if nums[mid] target:return midel…

chatgpt赋能python:Python在线播放——让您轻松畅览优质视频

Python在线播放——让您轻松畅览优质视频 在数字时代&#xff0c;视频已经成为了一种不可或缺的媒体形式&#xff0c;人们在在日常生活和工作中也更多地借助视频来实现信息传递和沟通。Python在线播放是当下最受欢迎的视频播放方式之一&#xff0c;相比于下载、实时流媒体等方…

Coursera自动驾驶2.3-2.4——传感器:IMU,GNSS,LiDAR

文章目录 一、3D几何和参考系1.旋转变换2.参考系 二、惯性测量单元1.陀螺仪2.加速计 三、全球导航卫星系统&#xff08;GNSS&#xff09;四、激光雷达1.激光雷达和测量模型&#xff08;1&#xff09;激光雷达概述&#xff08;2&#xff09;测量模型 2.点云3.平面拟合4.点云匹配…

Docker 基本管理

一、Docker 概述 Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵守了apache2.0协议开源。 Docker是在Linux容器里运行应用的开源工具&#xff0c;是一种轻量级的“虚拟机”。 Docker的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的、自…

rimraf : 无法加载文件 C:\Program Files\nodejs\rimraf.ps1,因为在此系统上禁止运行脚本。

问题&#xff1a; rimraf 运行 rimraf node_modules 命令报错&#xff1a;&#xff08;rimraf 前端同学可以多多了解&#xff09;rimraf : 无法加载文件 C:\Program Files\nodejs\rimraf.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/…

C#,码海拾贝(34)——求“赫申伯格矩阵”全部“特征值”的“QR方法”之C#源代码

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 矩阵类 /// 作者&#xff1a;周长发 /// 改进&#xff1a;深度混淆 /// https://blog.csdn.net/beijinghorn /// </summary> public partial class Matrix {…

chatgpt赋能python:Python基本词汇介绍

Python基本词汇介绍 Python是一种高级编程语言&#xff0c;它有着广泛的应用&#xff0c;从软件开发到数据科学。Python的语法简单易懂&#xff0c;它被广泛认为是一种易于学习和使用的编程语言。在本文中&#xff0c;我们将介绍一些Python基本词汇&#xff0c;让您能够更好地…

chatgpt赋能python:用Python统计奇偶数的方法

用Python统计奇偶数的方法 Python作为一种广泛应用于数据分析和科学计算的编程语言&#xff0c;具有许多内置函数和库&#xff0c;可以轻松地进行奇偶数的统计。这篇文章将向您展示如何使用Python统计奇偶数&#xff0c;并提供几个常见的示例。 Python奇偶数的定义 奇数是除…

ConcurrentHashMap核心源码(JDK1.8)

一、ConcurrentHashMap的前置知识扫盲 ConcurrentHashMap的存储结构&#xff1f; 数组 链表 红黑树 二、ConcurrentHashMap的DCL操作 HashMap线程不安全&#xff0c;在并发情况下&#xff0c;或者多个线程同时操作时&#xff0c;肯定要使用ConcurrentHashMap 无论是HashM…

Ceph分布式存储 原理+架构图详解

存储基础 单机存储设备 ●DAS&#xff08;直接附加存储&#xff0c;是直接接到计算机的主板总线上去的存储&#xff09; IDE、SATA、SCSI、SAS、USB 接口的磁盘 所谓接口就是一种存储设备驱动下的磁盘设备&#xff0c;提供块级别的存储 ●NAS&#xff08;网络附加存储&#x…

2、MySQL数据库基础

目录 MySQL 连接查询 表 约束 存储引擎 事务 索引 视图&#xff08;View&#xff09; 数据库的导入导出&#xff08;DBA命令&#xff09; 数据库设计三范式 MySQL sql、DB、DBMS分别是什么&#xff1f;它们之间的关系&#xff1f; DB&#xff1a; DataBase&#xff0…

软考A计划-电子商务设计师-系统开发项目管理

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…