【问题标题】:Right way to handle navigation using BLoC使用 BLoC 处理导航的正确方法
【发布时间】:2018-12-22 07:52:05
【问题描述】:

大家好,我正在为我目前正在开发的应用程序使用 BLoC,但有些情况我一无所知,比如当你登录时你会触发 API 调用并自然等待结果我会发送加载状态并显示加载器,但之后 这完成了如何处理例如导航到不同的屏幕。 我目前有这样的东西

typedef void LoginSuccessCallback();
    class LoginBloc(){
    LoginBloc(Api this.api,LoginSuccessCallback loginSuccesCallback){
      _login.switchMap((ev) => api.login(ev.payload.email,ev.payload.password)).listen((_) => loginSuccessCallback);
     }
    }

但我确信有更简洁的方法来处理这个问题我尝试搜索一些具有类似内容但找不到任何东西的样本。

【问题讨论】:

  • 您可能想让标题更具体一点:“如何使用 BLoC 登录/注销后处理导航”或类似内容。
  • 也许你想要这样的东西:dev.to/pedromassango/…

标签: dart flutter


【解决方案1】:

编辑:使用此解决方案几个月后,我注意到它存在一些问题:

  1. Android 硬件后退按钮不起作用
  2. 当您切换“检查”模式时,应用会重置。
  3. 无法进行转换
  4. 不保证不显示禁止路线

所以我不再推荐使用这种方法了!


对于正常的用户启动导航,您根本不需要 BLoC 模式。只需使用Navigator

登录是一种特殊情况。按照 BLoC 模式,提供isAuthenticated 流是有意义的:

abstract class MyBloc {
  Stream<bool> get isAuthenticated;
}

您的应用可能有 2 种不同的命名路由树:一种用于登录用户,一种用于匿名用户:

final Map<String, WidgetBuilder> anonymousRoutes = {
  '/': (context) => new LoginScreen(), // default for anon
  '/register': (context) => new RegisterScreen(),
};

final Map<String, WidgetBuilder> authenticatedRoutes = {
  '/': (context) => new HomeScreen(), // default for logged in
  '/savings': (context) => new SavingsScreen(),
  // ...
};

通常Navigator 及其命名路由与MaterialApp 紧密耦合,但您也可以定义自己的路由,在更新isAuthenticated 流时重新构建:

class MyApp extends StatelessWidget {
  const MyApp({Key key, this.bloc}) : super(key: key);

  final MyBloc bloc;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (BuildContext context, Widget child) {
        return StreamBuilder<bool>(
          stream: bloc.isAuthenticated,
          builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
            if (!snapshot.hasData) {
              return Text('loading...');
            }

            bool isAuthenticated = snapshot.data;
            return _buildNavigator(isAuthenticated);
          },
        );
      },
    );
  }
}

Navigator _buildNavigator(bool isAuthenticated) {
  // different route tree and different default route depending on auth state
  final routes = isAuthenticated ? authenticatedRoutes : anonymousRoutes;

  return Navigator(
    key: new ValueKey(isAuthenticated),
    onGenerateRoute: (RouteSettings settings) {
      final name = settings.name;
      return new MaterialPageRoute(
        builder: routes[name],
        settings: settings,
      );
    },
    onUnknownRoute: (RouteSettings settings) {
      throw Exception('unknown route');
    },
  );
}

可悲的是,现在 (2018-07-14) there are a 2 conflicting asserts 在 Flutter 代码中,您必须删除它才能使上面的代码正常工作(您可以使用您的 IDE 对其进行编辑):

packages\flutter\lib\src\widgets\app.dart 中的第 93 和 96 行

//assert(navigatorObservers != null),
//assert(onGenerateRoute != null || navigatorObservers == const <NavigatorObserver>[]),

【讨论】:

  • 您可以提供home 属性来避免断言
  • 我认为这会再次触发其他断言或导致生成导航器
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
  • 2014-05-02
  • 1970-01-01
  • 2012-08-21
  • 2021-05-20
  • 2017-09-09
相关资源
最近更新 更多