简介:
在Flutter中,导航器(Navigator)是管理应用程序中不同页面之间跳转的要害组件之一。其间的Navigator.of(context)
办法用于获取当前上下文(context)所在的导航器状况(NavigatorState),从而完成页面之间的导航操作。但是,有时候在运用Navigator.of(context)
办法时会遇到反常,本文将解释这个反常的原因并供给解决办法。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: OutlinedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => SecondPage()));
},
child: Text('跳转')),
),
),
);
}
}
反常情况:
当运用Navigator.of(context)
办法时,有时会抛出以下反常信息:
======== Exception caught by gesture ===============================================================
The following assertion was thrown while handling a gesture:
Navigator operation requested with a context that does not include a Navigator.
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.
When the exception was thrown, this was the stack:
该反常信息提示了咱们运用Navigator.of(context)
办法的上下文(context)必须是导航器(Navigator)的子级组件的上下文。
解决办法:
为了解决这个反常,咱们需要保证调用Navigator.of(context)
办法的上下文(context)是导航器(Navigator)的子级组件。下面是一个示例代码,演示了如何正确运用Navigator.of(context)
办法:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) { //context
return MaterialApp(
home: FirstPage(),
);
}
}
class FirstPage extends StatelessWidget {
const FirstPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: OutlinedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => SecondPage()));
},
child: Text('跳转'),
),
),
);
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Text('second page'),
),
);
}
}
现在,在FirstPage
组件中,Navigator.of(context)
办法将会正常工作,由于context
是FirstPage
组件的上下文,而且FirstPage
是作为MaterialApp
的子组件存在的。
探求Navigator.of(context)
源码: 为了更深入地了解Navigator.of(context)
办法的工作原理,咱们来看一下其源码完成:
static NavigatorState of(
BuildContext context, {
bool rootNavigator = false,
}) {
NavigatorState? navigator;
if (context is StatefulElement && context.state is NavigatorState) {
navigator = context.state as NavigatorState;
}
if (rootNavigator) {
navigator = context.findRootAncestorStateOfType<NavigatorState>() ?? navigator;
} else {
navigator = navigator ?? context.findAncestorStateOfType<NavigatorState>();
}
assert(() {
if (navigator == null) {
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!;
}
从源码中可以看到,Navigator.of(context)
办法首先查看上下文(context)是否是一个有状况组件(StatefulElement)且其状况(state)是NavigatorState
类型,假如是,那么该上下文的导航器状况便是咱们要获取的。接着,假如rootNavigator
参数为true
,则继续查找最近的根级导航器状况;假如rootNavigator
参数为false
,则继续查找最近的导航器状况。最后,假如没有找到导航器状况,则抛出反常。
在上述示例中,Navigator.of(context)
办法的可用性还与MaterialApp
的层级结构有关。下面是MaterialApp
包裹的组件层级结构:
- MaterialApp (_MaterialAppState)
- WidgetsApp (_WidgetsAppState)
- Navigator (NavigatorState)
- WidgetsApp (_WidgetsAppState)
class MaterialApp extends StatefulWidget {
State<MaterialApp> createState() => _MaterialAppState();
Widget _buildWidgetApp(BuildContext context) {
WidgetsApp
State<WidgetsApp> createState() => _WidgetsAppState();
Widget build(BuildContext context) {
Navigator(
restorationScopeId: 'nav',
key: _navigator,
initialRoute: _initialRouteName,
onGenerateRoute: _onGenerateRoute,
onGenerateInitialRoutes: widget.onGenerateInitialRoutes == null
? Navigator.defaultGenerateInitialRoutes
: (NavigatorState navigator, String initialRouteName) {
return widget.onGenerateInitialRoutes!(initialRouteName);
},
onUnknownRoute: _onUnknownRoute,
observers: widget.navigatorObservers!,
reportsRouteUpdateToEngine: true,
)
class Navigator extends StatefulWidget {
NavigatorState createState() => NavigatorState();
class NavigatorState extends State<Navigator> with TickerProviderStateMixin, RestorationMixin {
在这个层级结构中,MaterialApp
是一个StatefulWidget
,它创建了一个_MaterialAppState
的状况。_MaterialAppState
进一步创建了一个WidgetsApp
组件,也是一个StatefulWidget
,并同享相同的状况_WidgetsAppState
。在WidgetsApp
中,又创建了一个Navigator
组件,它的状况是NavigatorState
。
因此,Navigator.of(context)
办法实际上是通过上下文(context)向上查找最近的NavigatorState
状况对象,以便进行页面导航操作。
定论:
在运用Navigator.of(context)
办法时,咱们需要保证调用它的上下文(context)是导航器(Navigator)的子级组件,以避免抛出反常。这样,咱们就可以在Flutter应用程序中轻松完成页面之间的导航操作。
希望本文对您了解和运用Navigator.of(context)
办法有所帮助!假如您有任何问题或疑问,请随时发问。