Flutter 的 BuildContext

1,381 阅读3分钟

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战」。

上篇文章我们简单的说了main.dart 的StatelessWidgetStatefulWidget这俩个类。简单的了解Flutter StatelessWidget无状态组件和StatefulWidget有状态组件知识点。今天我们来说一下main.dart 里面的BuildContext

@override
Widget build(BuildContext context) {
   return Container();
}

什么是BuildContext?

BuildContext也是一个Widget(万物皆Widget😁)。我们知道在 Flutter 中,一切都是Widget。Flutter 项目的整个Widget都是以Widget树的形式显示,我们正是以BuildContext将父Widget和子Widget连接起来以显示它们之间的关系。 看上面的代码我们知道Flutter中的每个Widget都是由build方法创建的,而构建方法将 一个BuildContext作为参数。BuildContext这有助于构建方法找到要绘制的Widget,还有助于定位要在Widget树中绘制的Widget的位置。

当你想推送一条新路由时,你会写类似下面的这个方法:

Navigator.of(context).pushNamed('route')。

注意这里的上下文。它将用于获取NavigatorState树中最接近的祖先 Widget实例。然后在该实例上调用pushNamed方法。

一般来说,context 有两个作用:

  • 与祖先Widget互动(主要是获取/发布数据)。
  • 在屏幕上渲染后,获取屏幕大小和位置。

匿名的BuildContext。

每个 Widget 都有一个上下文,即使您看不到它,它们被称为BuildContext匿名.如:MaterialApp

return MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
     primarySwatch: Colors.blue,
  ),
  home: const MyHomePage(title: 'Flutter Demo Home Page'),
);

查看的代码,我们可以发现:

Widget build(BuildContext context) {
   Widget result = _buildWidgetApp(context);
   ....
}

Widget _buildWidgetApp(BuildContext context) {
   ...
}

BuildContext 之间的关系

BuildContext中子类总是与它最接近的超类,关系总是自下而上的。

image.png

如果你在 Context 中寻找的东西在最近的 parent 中没有找到,则会在 Root Widget 中搜索,如果在 Root Widget 中没有找到,则会抛出一个错误。

BuildContext 的一些方法

BuildContext 对象有几个有用的方法可以轻松执行需要在Widget树中完成的某些任务。更多的方法请查看BuildContext 对象的所有方法

findAncestorWidgetOfExactType()

findAncestorWidgetOfExactType<T extends Widget>()T?

返回给定类型 T 的最近祖先Widget。

findAncestorStateOfType()

findAncestorStateOfType<T extends State<StatefulWidget>>() → T?

返回最近的祖先 StatefulWidget 的 State 对象。

dependOnInheritedWidgetOfExactType()

dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) → T?

获取给定类型 T 的最近Widget,它必须是具体的 InheritedWidget 子类的类型,并将此构建上下文注册到该Widget,以便当该Widget更改时。

什么时候使用 BuildContext?

当您想向下传递数据而不必手动将其分配给每个Widget的配置时,而且您不想将它传递给每个构造函数,BuildContext就会非常有用,这样可以在任何地方访问它们。

final configuration = context.inheritFromWidgetOfExactType(Configuration);

在您的应用程序中的任何地方,您都可以使用BuildContext。所有通过调用的WidgetinheritFromWidgetOfExactType(Configuration)都会在配置更改时自动重建。

使用 BuildContext应该有什么需要注意的?

我们在使用 BuildContext 时总是需要小心,因为需要验证在方法中使用的上下文是否与我们需要的上下文是相同。

例如Theme.of(context) 寻找最近的 Theme。因此当某个Widget A 在其返回的Widget树中有一个主题并且它正在使用。 那么Theme.of(passing its own context) 那么build Widget A的 方法将找到作为Widget A 祖先的任何主题,而不会找到Widget A 中存在的主题。