【问题标题】:Flutter navigation using BLoC: The context used to push routes from the Navigator must be a descendant of a Navigator widget使用 BLoC 的 Flutter 导航:用于从 Navigator 推送路由的上下文必须是 Navigator 小部件的后代
【发布时间】:2019-07-12 04:01:46
【问题描述】:

我正在使用 BLoC,我需要从 PageOne 导航到 PageTwo 并能够使用后退按钮返回,我不知道这是否是处理此问题的正确方法。 当函数 _navigateToPage2 被调用时,我也遇到了错误。

用于从 Navigator 推送或弹出路由的上下文必须是作为 Navigator 小部件后代的小部件的上下文。

class SimpleBlocDelegate extends BlocDelegate {

  @override
  void onTransition(Transition transition) {
     print(transition);
  }

  @override
  void onError(Object error, StackTrace stacktrace) {
      print(error);
   }
}



void main() {
  BlocSupervisor().delegate = SimpleBlocDelegate();
  runApp(MyApp(userRepository: UserRepository(GuriApi())));
}

class MyApp extends StatefulWidget {
  final UserRepository userRepository;

  MyApp({Key key, @required this.userRepository}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  AuthenticationBloc _authenticationBloc;
  UserRepository get _userRepository => widget.userRepository;

  @override
  void initState() {
    _authenticationBloc = AuthenticationBloc(userRepository: _userRepository);
    _authenticationBloc.dispatch(AppStarted());
    super.initState();
  }

  @override
  void dispose() {
    _authenticationBloc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<AuthenticationBloc>(
      bloc: _authenticationBloc,
      child: MaterialApp(
        theme: new ThemeData(
            fontFamily: 'Monserrat',
            primaryColor: Colors.lightBlue[50],
            accentColor: Colors.white),
        home: BlocBuilder<AuthenticationEvent, AuthenticationState>(
          bloc: _authenticationBloc,
          builder: (BuildContext context, AuthenticationState state) {
            if (state is AuthenticationUninitialized) {
              return SplashPage();
            }
            if (state is AuthenticationAuthenticated) {
              return Home(userRepository: _userRepository);
            }
            if (state is AuthenticationUnauthenticated) {
              return LoginPage(userRepository: _userRepository);
            }
            if (state is AuthenticationLoading) {
              return LoadingIndicator();
            }
            if (state is PageOneSelected) {
              return PageOne();
            }
            if (state is PageTwoSelected) {
              _navigateToPage2();
            }
          },
        ),
      ),
    );
  }

  _navigateToPage2() {
    Navigator.of(context).push<bool>(
        MaterialPageRoute(
            builder: (BuildContext context) =>
                PageTwo(userRepository: _userRepository)));
  }
}

【问题讨论】:

    标签: flutter navigation bloc


    【解决方案1】:

    有必要在你的小部件中做这样的事情:

         if (state is PageTwoSelected) {
             WidgetsBinding.instance.addPostFrameCallback((_){
                Navigator.push(context, 
                  MaterialPageRoute(builder: (context) =>
                    PageTwo(userRepository: _userRepository))
                );
             });
         }
    

    这是必要的,因为如果在小部件仍在构建(处于脏状态)时发生导航,Flutter 将抛出异常。

    通过将其嵌套在 addPostFrameCallback 的回调中,您基本上是在说当小部件完成构建时,然后执行导航代码。

    你可以阅读更多关于它的信息here,在 cmets 中有解释。

    【讨论】:

      【解决方案2】:

      我认为最好通过在initState中订阅bloc状态变化来处理导航:

      @override
      void initState() {
          super.initState();
      
          bloc.state.listen((state) {
              if (state is PageOneSelected) {
                  _navigateToPage2();
              } else if (state is PageTwoSelected) {
                  _navigateToPage2();
              }
          });
      }
      

      在构建方法中显示一些其他小部件。您的代码中发生错误,因为 blocBuilder 必须返回 Widget 但在 PageTwoSelected 状态的情况下您什么也不返回。

      【讨论】:

      • 您先生刚刚救了我的命。我已经在整个互联网上搜索了答案。感谢您让这个社区变得更美好
      猜你喜欢
      • 1970-01-01
      • 2021-05-28
      • 2021-03-16
      • 2021-08-22
      • 2021-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多