持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,[点击查看活动详情](juejin.cn/post/709970… "juejin.cn/post/709970…
简介
我们知道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。