如何在 Bloc Login Flutter 中使用带有身份验证的 NavigationDrawer 路由

Posted

技术标签:

【中文标题】如何在 Bloc Login Flutter 中使用带有身份验证的 NavigationDrawer 路由【英文标题】:How to use routes in Bloc Login Flutter for NavigationDrawer with authentication 【发布时间】:2020-05-22 10:24:13 【问题描述】:

我实现了 Flutter Bloc Login 示例,与指南页面 here 完全一样:

接下来,我在页面中添加了 NavigationDrawer。

但我不知道如何跨页面导航,我尝试了正常的 Navigator.push 但不起作用,我在 MaterialApp 中使用了 routes 不幸的是不是那样工作的。

ma​​in.dart

void main() 
  BlocSupervisor.delegate = SimpleBlocDelegate();
  final userRepository = UserRepository();
  runApp(
    BlocProvider<AuthenticationBloc>(
      create: (context) 
        return AuthenticationBloc(userRepository: userRepository)
          ..add(AppStarted());
      ,
      child: App(userRepository: userRepository),
    ),
  );


class App extends StatelessWidget 
  final UserRepository userRepository;
  App(Key key, @required this.userRepository) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
        builder: (context, state) 
          if (state is AuthenticationAuthenticated) 
            //return Counter();
            //return ListPage();
            return ProfilePage();
          
          if (state is AuthenticationUnauthenticated) 
            return LoginPage(userRepository: userRepository);
          
          if (state is AuthenticationLoading) 
            return LoadingIndicator();
          
          return SplashPage();
        ,
      ),
      initialRoute: '/',
      routes: 
        '/': (context) => SplashPage(),
        '/counter': (context) => Counter(),
        '/profile': (context) => ProfilePage(),
        '/list': (context) => ListPage(),
      ,
    );
  

navigation_drawer.dart

  Widget build(BuildContext context) 
    return Drawer(
      child: ListView(
        // Important: Remove any padding from the ListView.
        padding: EdgeInsets.zero,
        children: <Widget>[
          Container(...),
          ListTile(
            title: Text('Profile'),
            onTap: () 
              /* TODO: check token is not null */
              Navigator.pushNamed(context, '/profile');

              ,
          ),
          ListTile(
            title: Text('Counter'),
            onTap: () 
              Navigator.pushNamed(context, '/counter');
            ,
          ),
          ListTile(
            title: Text('My List'),
            onTap: () 
              Navigator.pushNamed(context, '/list');
            ,
          ),
        ],
      ),
    );
  

【问题讨论】:

【参考方案1】:

这很简单,您忘记使用 Scaffold 小部件作为 Material 小部件的子小部件,而 Scaffold 有一个属性抽屉,您可以将抽屉传递给它。如下:

ma​​in.dart

void main() 
  BlocSupervisor.delegate = SimpleBlocDelegate();
  final userRepository = UserRepository();
  runApp(
    BlocProvider<AuthenticationBloc>(
      create: (context) 
        return AuthenticationBloc(userRepository: userRepository)
          ..add(AppStarted());
      ,
      child: App(userRepository: userRepository),
    ),
  );


class App extends StatelessWidget 
  final UserRepository userRepository;
  App(Key key, @required this.userRepository) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        drawer: build(context),
        body: BlocBuilder<AuthenticationBloc, AuthenticationState>(
          builder: (context, state) 
            if (state is AuthenticationAuthenticated) 
              //return Counter();
              //return ListPage();
              return ProfilePage();
            
            if (state is AuthenticationUnauthenticated) 
              return LoginPage(userRepository: userRepository);
            
            if (state is AuthenticationLoading) 
              return LoadingIndicator();
            
            return SplashPage();
          ,
        ),
      ),
      initialRoute: '/',
      routes: 
        '/': (context) => SplashPage(),
        '/counter': (context) => Counter(),
        '/profile': (context) => ProfilePage(),
        '/list': (context) => ListPage(),
      ,
    );
  

navigation_drawer.dart

Widget build(BuildContext context) 
  return Drawer(
    child: ListView(
      // Important: Remove any padding from the ListView.
      padding: EdgeInsets.zero,
      children: <Widget>[
        Container(...),
        ListTile(
          title: Text('Profile'),
          onTap: () 
            /* TODO: check token is not null */
            Navigator.pushNamed(context, '/profile');

          ,
        ),
        ListTile(
          title: Text('Counter'),
          onTap: () 
            Navigator.pushNamed(context, '/counter');
          ,
        ),
        ListTile(
          title: Text('My List'),
          onTap: () 
            Navigator.pushNamed(context, '/list');
          ,
        ),
      ],
    ),
  );

但我不建议你以这种方式使用 bloc。

【讨论】:

以上是关于如何在 Bloc Login Flutter 中使用带有身份验证的 NavigationDrawer 路由的主要内容,如果未能解决你的问题,请参考以下文章

Flutter BLoC 用户登录

Flutter BLoC 库中带有验证的文本字段

flutter - bloc - 我如何在我的 Ui 中使用 FutureBuilder 来正确实现 Bloc 架构

需要帮助了解 flutter_bloc 如何注入 bloc

Flutter - 如何构建多个嵌套的 BLoC?

FLutter - 如何在 BLoC 初始化时调度事件