Flutter Redux Navigator GlobalKey.currentState возвращает ноль
Я разрабатываю Flutter с Redux.
Когда пользователь запускает приложение, я хочу Redux
автоматически dispatch
action
, Это действие сделает Navigator
толкать разные маршруты зависимо.
Этот фрагмент, предоставленный участником Flutter dev, использует GlobalKey
использовать Navigator
внутри middleware
,
После этого я организую свой код следующим образом:
main.dart
void main() {
final store = new Store(appStateReducer,
middleware:createRouteMiddleware()
);
runApp(new MyApp(store));
}
class MyApp extends StatelessWidget {
final Store<AppState> store;
MyApp(this.store);
@override
Widget build(BuildContext context) {
return new StoreProvider<AppState>(
store: store,
child: MaterialApp(
routes: {
Routes.REGISTER: (context) {
return RegisterScreenContainer();
},
Routes.SET_PROFILE: (context) {
return SetProfileScreenContainer();
},
//Routes.HOME = "/" so this route will be run first
Routes.HOME: (context) {
return StoreBuilder<AppState>(
//onInit is called to dispatch an action automatically when the application starts. The middleware will catch this and navigate to the appropriate route.
onInit: (store) => store.dispatch(
ChangeRoute(routeStateType: RouteStateType.Register)),
builder: (BuildContext context, Store vm) {
return RegisterScreenContainer();
},
);
},
}));
}
}
middleware.dart
Middleware<AppState> createRouteMiddleware(
{@required GlobalKey<NavigatorState> navigatorKey}) {
final changeRoute = _createChangeRouteMiddleware(navigatorKey: navigatorKey);
return TypedMiddleware<AppState, ChangeRoute>(changeRoute);
}
Middleware<AppState> _createChangeRouteMiddleware(
{@required GlobalKey<NavigatorState> navigatorKey}) {
print(navigatorKey.currentState);
return (Store store, action, NextDispatcher next) async {
switch ((action.routeStateType as RouteStateType)) {
case RouteStateType.Home:
navigatorKey.currentState.pushNamed(Routes.HOME);
break;
case RouteStateType.Register:
//The middleware intercepts and push the appropriate route depending on the action
navigatorKey.currentState.pushNamed(Routes.REGISTER);
break;
default:
break;
}
next(action);
};
}
И это ошибка, которую я получил
[ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter ( 2544): NoSuchMethodError: The method 'pushNamed' was called on null.
E/flutter ( 2544): Receiver: null
E/flutter ( 2544): Tried calling: pushNamed("/register")
Это означает, что action
был успешно отправлен, однако, currentState
из navigatorKey
было null
,
Что мне здесь не хватает?
Обратите внимание, что я знаю об этом, казалось бы, похожем вопросе, который на самом деле не относится к моему вопросу. Даже когда я объединяю main.dart и middleware.dart в один файл, он все равно не работает.
1 ответ
Я решил эту проблему, имея глобальную клавишу навигатора в отдельном файле. Затем я использовал это в своем материале приложения и в промежуточном программном обеспечении.
Я поместил ключ навигатора в мой файл keys.dart:
import 'package:flutter/widgets.dart';
class NoomiKeys {
static final navKey = new GlobalKey<NavigatorState>();
}
Добавил ключ к виджету MaterialApp "navigatorKey: NoomiKeys.navKey" в моем файле main.dart (много кода удалено, чтобы его было быстрее читать):
import 'package:noomi_nursing_home_app/keys.dart';
@override
Widget build(BuildContext context) {
return StoreProvider<AppState>(
store: store,
child: MaterialApp(
//Add the key to your materialApp widget
navigatorKey: NoomiKeys.navKey,
localizationsDelegates: [NoomiLocalizationsDelegate()],
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
И используйте его в navigate_middleware.dart;
import 'package:noomi_nursing_home_app/actions/actions.dart';
import 'package:noomi_nursing_home_app/keys.dart';
import 'package:redux/redux.dart';
import 'package:noomi_nursing_home_app/models/models.dart';
List<Middleware<AppState>> navigateMiddleware() {
final navigatorKey = NoomiKeys.navKey;
final navigatePushNamed = _navigatePushNamed(navigatorKey);
return ([
TypedMiddleware<AppState, NavigatePushNamedAction>(navigatePushNamed),
]);
}
Middleware<AppState> _navigatePushNamed(navigatorKey) {
return (Store<AppState> store, action, NextDispatcher next) {
next(action);
navigatorKey.currentState.pushNamed(action.to);
};
}
Похоже , вы забыли объявить и передать navigatorKey промежуточному программному обеспечению
final navigatorKey = GlobalKey<NavigatorState>();
void main() {
final store = Store(appStateReducer,
middleware:createRouteMiddleware(navigatorKey: navigatorKey)
);
runApp(MyApp(store));
}
и в вашем MaterialApp тоже отсутствует navigatorKey
MaterialApp(
navigatorKey: navigatorKey
routes: /* your routes */
)