flutter系列之:构建Widget的上下文环境BuildContext详解
简介
我们知道Flutter中有两种Widget,分别是StatelessWidget和StatefulWidget,StatelessWidget中有一个build方法来创建对应的Widget,虽然StatefulWidget中没有对应的build方法,但是和StatefulWidget对应的State中也有同样的build方法。
这个build方法就是用来创建Widget的核心方法。
我们来看下build方法的定义:
Widget build(BuildContext context);
build方法传入一个BuildContext对象,返回一个Widget对象,也就是说这个BuildContext中包含了要创建的Widget的所有信息。这个BuildContext被称为是Widget的上下文构建环境。
那么BuildContext有什么特性呢?我们又该如何使用BuildContext呢?一起来看看吧。
BuildContext的本质
还记得flutter中的三颗树吗?

他们分别是Widgets树,Element树和Render树。其中Widgets树和Element树是一一对应的。而Render树和Element中的RenderObjectElement是一一对应的。
事实上BuildContext就是一个Element对象。怎么说呢?
我们先看下BuildContext的定义:
abstract class BuildContext {
Widget get widget;
...
}
BuildContext是一个抽象类,我们再看一下Element类的定义:
abstract class Element extends DiagnosticableTree implements BuildContext {
可以看到,Element对象实现了BuildContext接口,而每一个BuildContext都有一个和其绑定的Widget对象。
经过复杂的关系传递运算,我们可以知道Element对象和Widget对象从代码层面来说,确实是一一对应的。
BuildContext和InheritedWidget
InheritedWidget是一种widget用来在tree中向下传递变动信息,在tree的子节点中,可以通过调用BuildContext.dependOnInheritedWidgetOfExactType在子节点中查找最近的父InheritedWidget,从而将当前的BuildContext绑定的widget和InheritedWidget建立绑定关系,从而在下次InheritedWidget发生变动的时候,会自动触发BuildContext绑定的widget的rebuild方法。
听起来好像很复杂的样子,但是实际上很简单,我们举个例子,首先我们需要定义一个Widget用来继承InheritedWidget:
class FrogColor extends InheritedWidget {
const FrogColor({
Key? key,
required this.color,
required Widget child,
}) : super(key: key, child: child);
final Color color;
static FrogColor of(BuildContext context) {
final FrogColor? result = context.dependOnInheritedWidgetOfExactType<FrogColor>();
assert(result != null, 'No FrogColor found in context');
return result!;
}
@override
bool updateShouldNotify(FrogColor old) => color != old.color;
}
在这个方法中,我们需要定义一个of方法,这个该方法中,我们调用context.dependOnInheritedWidgetOfExactType方法,用来查找离BuildContext最近的FrogColor。
然后可以这样使用:
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: FrogColor(
color: Colors.green,
child: Builder(
builder: (BuildContext innerContext) {
return Text(
'Hello Frog',
style: TextStyle(color: FrogColor.of(innerContext).color),
);
},
),
),
);
}
}
我们的本意是希望child中的Text组件的style根据父widget中的FrogColor的color来进行变化。所以在子组件的style中调用了FrogColor.of(innerContext)方法,对InheritedWidget进行查找,同时建立绑定关系。
在BuildContext中,有两个查找并且进行绑定的方法,他们是:
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });
T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object? aspect });
两者的区别是,后者限定了查找的类型。
除了dependOn之外,BuildContext还提供了两个查找的方法:
InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();
T? findAncestorWidgetOfExactType<T extends Widget>();
T? findAncestorStateOfType<T extends State>();
T? findRootAncestorStateOfType<T extends State>();
T? findAncestorRenderObjectOfType<T extends RenderObject>();
他们和depend的区别是,他们不会建立依赖关系,只是单纯的进行查找。
BuildContext的层级关系
因为每个widget都有一个BuildContext,所以我们在使用的过程中一定要注意传入的BuildContext到底绑定的是哪个widget。
如下面的代码所示:
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: FrogColor(
color: Colors.green,
child: Builder(
builder: (BuildContext innerContext) {
return Text(
'Hello Frog',
style: TextStyle(color: FrogColor.of(innerContext).color),
);
},
),
),
);
}
}
在FrogColor的child中,我们创建了一个新的Builder,并提供了一个新的innerContext。
为什么要这样做呢?因为如果我们不创建子innnerContext的话,使用的context就是Scaffold的,这样FrogColor.of将会找不到要找的对象,从而报错。
所以我们在使用BuildContext的时候,一定要注意。
总结
BuildContext是构建Widget的基础,它也提供了一些非常有用的查找和绑定的功能,希望能对大家有所帮助。
更多内容请参考 http://www.flydean.com/04-flutter-buildcontext/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
flutter系列之:构建Widget的上下文环境BuildContext详解的更多相关文章
- 转载 CSS3 经典教程系列:CSS3 盒阴影(box-shadow)详解
目标大纲 文章转载 CSS3 经典教程系列:CSS3 盒阴影(box-shadow)详解 IE中CSS-filter滤镜小知识大全 CSS实现跨浏览器兼容性的盒阴影效果
- Spark Streaming揭秘 Day28 在集成开发环境中详解Spark Streaming的运行日志内幕
Spark Streaming揭秘 Day28 在集成开发环境中详解Spark Streaming的运行日志内幕 今天会逐行解析一下SparkStreaming运行的日志,运行的是WordCountO ...
- Nginx+Tomcat的服务器端环境配置详解
这篇文章主要介绍了Nginx+Tomcat的服务器端环境配置详解,包括Nginx与Tomcat的监控开启方法,需要的朋友可以参考下 Nginx+tomcat是目前主流的Javaweb架构,如何让ngi ...
- Windows GTK+ 环境搭建(详解)
来源:http://blog.sina.com.cn/s/blog_a6fb6cc901017ygy.html Windows GTK+ 环境搭建 最近要做界面的一些东西,但是对微软提供的类库MFC不 ...
- 单元测试系列之十一:Jmockit之mock特性详解
本文是Jmockit学习过程中,根据官网所列的工具特性进行解读. 1.调用次数约束(Invocation count constraints) 可以通过调用计数约束来指定预期和/或允许匹配给定期望的调 ...
- MySQL高可用方案-PXC(Percona XtraDB Cluster)环境部署详解
MySQL高可用方案-PXC(Percona XtraDB Cluster)环境部署详解 Percona XtraDB Cluster简称PXC.Percona Xtradb Cluster的实现是在 ...
- net core体系-web应用程序-4net core2.0大白话带你入门-5asp.net core环境变量详解
asp.net core环境变量详解 环境变量详解 Windows操作系统的环境变量在哪设置应该都知道了. Linux(centos版本)的环境变量在/etc/profile里面进行设置.用户级的 ...
- Maya 常用环境变量详解
Maya 常用环境变量详解 前言: Maya 的环境变量让用户可以很方便的自定义 Maya 的功能. 在 Maya 的 Help 帮助文档中有专门的一个章节< Environment Varia ...
- Python环境搭建详解(Window平台)
前言 Python,是一种面向对象的解释型计算机程序设计语言,是纯粹的自由软件,Python语法简洁清晰,特色是强制用空白符作为语句缩进,具有丰富和强大的库,它常被称为胶水语言. Python是一种解 ...
随机推荐
- plt.figure()的使用,plt.plot(),plt.subplot(),plt.subplots()和图中图
参考:https://blog.csdn.net/m0_37362454/article/details/81511427 matplotlib官方文档:https://matplotlib.org/ ...
- Java创建数据库新建表及初始化表
方法一 package com.crt.openapi; import java.sql.DriverManager;import java.sql.ResultSet;import java.io. ...
- Java 泛型中的通配符
本文内容如下: 1. 什么是类型擦除 2.常用的 ?, T, E, K, V, N的含义 3.上界通配符 < ?extends E> 4.下界通配符 < ?super E> 5 ...
- 论文解读(SR-GNN)《Shift-Robust GNNs: Overcoming the Limitations of Localized Graph Training Data》
论文信息 论文标题:Shift-Robust GNNs: Overcoming the Limitations of Localized Graph Training Data论文作者:Qi Zhu, ...
- SpringCloud Alibaba整合Sentinel
SpringCloud Alibaba整合Sentinel Sentinel 控制台 1. 概述 Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理.监控(单机和集群),规则 ...
- 利用kubernetes资源锁完成自己的HA应用
Backgroud 前一章中,对kubernetes的选举原理进行了深度剖析,下面就通过一个example来实现一个,利用kubernetes提供的选举机制完成的高可用应用. 对于此章需要提前对一些概 ...
- Java 集合常见知识点&面试题总结(上),2022 最新版!
你好,我是 Guide.秋招即将到来(提前批已经开始),我对 JavaGuide 的内容进行了重构完善,公众号同步一下最新更新,希望能够帮助你. 你也可以在网站(javaguide.cn)上在线阅读, ...
- 数组容器(ArrayList)设计与Java实现,看完这个你不懂ArrayList,你找我!!!
数组容器(ArrayList)设计与Java实现 本篇文章主要跟大家介绍我们最常使用的一种容器ArrayList.Vector的原理,并且自己使用Java实现自己的数组容器MyArrayList,让自 ...
- 一文聊透 Netty IO 事件的编排利器 pipeline | 详解所有 IO 事件的触发时机以及传播路径
欢迎关注公众号:bin的技术小屋,本文图片加载不出来的话可查看公众号原文 本系列Netty源码解析文章基于 4.1.56.Final版本 1. 前文回顾 在前边的系列文章中,笔者为大家详细剖析了 Re ...
- ACWing94. 递归实现排列型枚举
题面 把 1∼n 这 n个整数排成一行后随机打乱顺序,输出所有可能的次序. 输入格式 一个整数 n. 输出格式 按照从小到大的顺序输出所有方案,每行 1 个. 首先,同一行相邻两个数用一个空格隔开. ...