Navigator.of(context).push(MaterialPageRoute(builder: (context){
return DemoPage();
}));
複製代碼
在平常的項目開發中,咱們通常push一個新頁面是用上面的方法的,利用Navigator.of(context)來進行push或者pop操做。bash
缺點:這種狀況是必須傳context的,目的是爲了利用Navigator.of(context)來獲取到NavigatorState對象,而後才能進行push或者pop操做。ide
那若是我要實如今項目的任何地方均可以push一個新頁面的話,而這個地方有可能獲取不到context,因此這個時候,就須要實現無context跳轉。post
無context跳轉,本質就是沒必要要咱們每次都去傳context參數,而後利用一些操做直接去獲取到當前的NavigatorState。ui
這裏貼一下相關的源碼,具體的你們能夠本身去看源碼。 MaterialApp類: this
WidgetsApp類:能夠看出,咱們定義的navigatorKey,最後是會傳給Navigator的key值,因此咱們在外面就能夠經過key.currentState()方法來獲取到這裏的NavigatorState對象了。spa
class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserver {
GlobalKey<NavigatorState> _navigator;
void _updateNavigator() {
_navigator = widget.navigatorKey ?? GlobalObjectKey<NavigatorState>(this);
}
@override
Widget build(BuildContext context) {
Widget navigator;
if (_navigator != null) {
navigator = Navigator(
key: _navigator,
initialRoute: WidgetsBinding.instance.window.defaultRouteName != Navigator.defaultRouteName
? WidgetsBinding.instance.window.defaultRouteName
: widget.initialRoute ?? WidgetsBinding.instance.window.defaultRouteName,
onGenerateRoute: _onGenerateRoute,
onUnknownRoute: _onUnknownRoute,
observers: widget.navigatorObservers,
);
}
}
複製代碼
static GlobalKey<NavigatorState> navigatorKey=GlobalKey();
複製代碼
MaterialApp(
navigatorKey: Router.navigatorKey,
)
複製代碼
navigatorKey.currentState.pushNamed("/login");
複製代碼
注意:NavigatorObserver裏面定義了一個NavigatorState對象navigator,因此咱們能夠經過自定義NavigatorObserver,而後直接利用這個navigator對象來作頁面push或者pop操做,這樣的話,咱們就不用本身去利用context去獲取navigatorState對象了。 3d
class CustomNavigatorObserver extends NavigatorObserver{
static CustomNavigatorObserver _instance;
static CustomNavigatorObserver getInstance() {
if (_instance == null) {
_instance = CustomNavigatorObserver();
}
return _instance;
}
}
複製代碼
MaterialApp(
navigatorObservers: [CustomNavigatorObserver()],
)
複製代碼
CustomNavigatorObserver.getInstance().navigator.pushNamed("/login");
複製代碼
其實這類文章掘金上面也有,本身寫這篇文章,主要是本身作下總結。code
大佬們的文章連接:cdn