Flutter Redux导航器GlobalKey.currentState返回null

10

我正在使用Flutter和Redux进行开发。

当用户开始使用应用程序时,我希望Redux自动dispatch一个action。这个action将使Navigator推送不同的路由。

这段代码片段来自一位Flutter开发人员使用GlobalKeymiddleware中使用Navigator

接下来,我按照以下方式组织我的代码:

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 已经成功调用,但是 navigatorKeycurrentStatenull

我错过了什么?

请注意,我知道 这个看似相似的问题 并不适用于我的问题。即使我将 main.dartmiddleware.dart 合并成一个文件,它仍然无法正常工作。

2个回答

16

我通过将全局导航键放在单独的文件中来解决了这个问题。 然后我在我的MaterialApp和中间件中使用它。

我将导航键放在我的keys.dart文件中:

import 'package:flutter/widgets.dart';
class NoomiKeys {
  static final navKey = new GlobalKey<NavigatorState>();
}
在我的main.dart文件中,将键添加到MaterialApp小部件“navigatorKey:NoomiKeys.navKey”,已删除大量代码以使其更易于阅读。
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);
  };
}

1

看起来您忘记在中间件中声明和传递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 */
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接