【Flutter学习】一些重要的概念之of(context)方法
在flutter中我们经常会使用到这样的代码
//打开一个新的页面 Navigator.of(context).push //打开Scaffold的Drawer Scaffold.of(context).openDrawer //获取display1样式文字主题 Theme.of(context).textTheme.display1
那么这个of(context)到底是个什么呢。我们这里以Navigator打开新页面为例。
static NavigatorState of( BuildContext context, { bool rootNavigator = false, bool nullOk = false, }) { //关键代码-----------------------------------------v final NavigatorState navigator = rootNavigator ? context.rootAncestorStateOfType(const TypeMatcher<NavigatorState>()) : context.ancestorStateOfType(const TypeMatcher<NavigatorState>()
); //关键代码----------------------------------------^ assert(() { if (navigator == null && !nullOk) { throw FlutterError( 'Navigator operation requested with a context that does not include a Navigator.\n' 'The context used to push or pop routes from the Navigator must be that of a ' 'widget that is a descendant of a Navigator widget.' ); } return true; }()); return navigator; }
可以看到,关键代码部分通过context.rootAncestorStateOfType向上遍历 Element tree,并找到最近匹配的 NavigatorState。也就是说of实际上是对context跨组件获取数据的一个封装。
而我们的Navigator的 push操作就是通过找到的 NavigatorState 来完成的。
不仅如此,BuildContext还有许多方法可以跨组件获取对象
ancestorInheritedElementForWidgetOfExactType(Type targetType) → InheritedElement ancestorRenderObjectOfType(TypeMatcher matcher) → RenderObject ancestorStateOfType(TypeMatcher matcher) → State ancestorWidgetOfExactType(Type targetType) → Widget findRenderObject() → RenderObject inheritFromElement(InheritedElement ancestor, { Object aspect }) → InheritedWidget inheritFromWidgetOfExactType(Type targetType, { Object aspect }) → InheritedWidget rootAncestorStateOfType(TypeMatcher matcher) → State visitAncestorElements(bool visitor(Element element)) → void visitChildElements(ElementVisitor visitor) → void
需要注意的是,在 State 中 initState阶段是无法跨组件拿数据的,只有在didChangeDependencies之后才可以使用这些方法。
回顾问题
我们现在再来看看之前遇到的 当前 context 不包含 Navigator 这个问题是不是很简单了呢。
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: FlatButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) => SecondPage())); }, child: Text('跳转')), ), ), ); } }
当我们在 build 函数中使用Navigator.of(context)的时候,这个context实际上是通过 MyApp 这个widget创建出来的Element对象,而of方法向上寻找祖先节点的时候(MyApp的祖先节点)并不存在MaterialApp,也就没有它所提供的Navigator。
所以当我们把Scaffold部分拆成另外一个widget的时候,我们在FirstPage的build函数中,获得了FirstPage的BuildContext,然后向上寻找发现了MaterialApp,并找到它提供的Navigator,于是就可以愉快进行页面跳转了。
分类:
Flutter
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2017-06-28 xcode工程编译错误:一般错误总结
2017-06-28 解决pathForResource返回nil, 无法读取plist文件问题
2017-06-28 xcode工程编译错误:error: Couldn’t materialize