Flutter-根据登录状态使用不同的路由启动应用程序

时间:2018-11-07 17:19:11

标签: navigation flutter

我正在寻找一种方法来根据登录状态在应用启动时显示不同的屏幕。例如,我定义了以下路由:

  • / home
  • /登录
  • /设置

自然,我将检查用户是否已经使用main()方法登录,然后将我的MaterialApp的initialRoute设置为/ login或/ home。成功登录后,我可以调用Navigator.pushReplacement导航到/ home,并从堆栈中删除登录屏幕。不幸的是,我总是必须为/定义一个路由或设置MaterialApp的home属性。因此,如果我将/设置为空白的Container(),则此Container将在导航堆栈中,并且用户可以返回到该空白屏幕。

我想到的两个选择是:

  • 将MaterialApp的home属性设置为HomeScreen或LoginScreen
  • 如果用户尚未登录,请使用HomeScreen的build()方法返回LoginScreen

这两个选项都是可行的,但是为了更新home属性或HomeScreen,我必须提出一些重载逻辑并重新设置状态。

有什么想法在Flutter中处理此类案件的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

也许您可以这样做。想象一下,您有一个带有异步方法isLogged的Auth类。

class Auth {
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

  Future<bool> isLogged() async {
    try {
      final FirebaseUser user = await _firebaseAuth.currentUser();
      return user != null;
    } catch (e) {
      return false;
    }
  }
}

您可以使用myApp构造函数传递initialRoute,并根据登录状态决定初始路由。然后,您可以将myApp的实例传递给runApp

void main() async {
  final Auth _auth = Auth();
  final bool isLogged = await _auth.isLogged();
  final MyApp myApp = MyApp(
    initialRoute: isLogged ? '/home' : '/',
  );
  runApp(myApp);
}

然后,您必须修改myApp类以在构造函数中传递初始路由:

class MyApp extends StatelessWidget {
  final String initialRoute;

  MyApp({this.initialRoute});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dynamic Route Demo',
      initialRoute: initialRoute,
      routes: {
        '/': (context) => LoginPage(),
        '/home': (context) => HomePage(),
        '/settings': (context) => SettingsPage(),
      },
    );
  }
}

希望这会有所帮助。

答案 1 :(得分:0)

您应该做的是移动到/ login路由(或其他您喜欢的登录名),并将其设置为initialRoute。基于此,您可以修改应用程序的onGenerateInitialRoutes属性,以确保实际上没有将路由推送到导航器历史记录中。这样,您将覆盖defaultGenerateInitialRoutes,它会将这些原始状态推送到导航器。在Flutter网站上检查此代码段。

https://api.flutter.dev/flutter/widgets/Navigator/defaultGenerateInitialRoutes.html

也将其复制到此处,以防万一将来链接不可用。

defaultGenerateInitialRoutes方法列表 defaultGenerateInitialRoutes(NavigatorState导航器,字符串 initialRouteName)将路由名称转换为一组Route对象。

这是onGenerateInitialRoutes的默认值,如果 initialRoute不为null。

如果此字符串包含任何/字符,则将字符串拆分为 从字符串开头到最后的那些字符和子字符串 每个这样的角色又被用作推入路线。

例如,如果将路径/ stocks / HOOLI用作初始路径, 然后导航器将在启动时推送以下路线:/, / stocks,/ stocks / HOOLI。这样可以进行深层链接,同时允许 维护可预测的路线历史的应用程序。

static List<Route<dynamic>> defaultGenerateInitialRoutes(NavigatorState navigator, String initialRouteName) {
  final List<Route<dynamic>> result = <Route<dynamic>>[];
  if (initialRouteName.startsWith('/') && initialRouteName.length > 1) {
    initialRouteName = initialRouteName.substring(1); // strip leading '/'
    assert(Navigator.defaultRouteName == '/');
    List<String> debugRouteNames;
    assert(() {
      debugRouteNames = <String>[ Navigator.defaultRouteName ];
      return true;
    }());
    result.add(navigator._routeNamed<dynamic>(Navigator.defaultRouteName, arguments: null, allowNull: true));
    final List<String> routeParts = initialRouteName.split('/');
    if (initialRouteName.isNotEmpty) {
      String routeName = '';
      for (final String part in routeParts) {
        routeName += '/$part';
        assert(() {
          debugRouteNames.add(routeName);
          return true;
        }());
        result.add(navigator._routeNamed<dynamic>(routeName, arguments: null, allowNull: true));
      }
    }
    if (result.last == null) {
      assert(() {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception:
              'Could not navigate to initial route.\n'
              'The requested route name was: "/$initialRouteName"\n'
              'There was no corresponding route in the app, and therefore the initial route specified will be '
              'ignored and "${Navigator.defaultRouteName}" will be used instead.'
          ),
        );
        return true;
      }());
      result.clear();
    }
  } else if (initialRouteName != Navigator.defaultRouteName) {
    // If initialRouteName wasn't '/', then we try to get it with allowNull:true, so that if that fails,
    // we fall back to '/' (without allowNull:true, see below).
    result.add(navigator._routeNamed<dynamic>(initialRouteName, arguments: null, allowNull: true));
  }
  // Null route might be a result of gap in initialRouteName
  //
  // For example, routes = ['A', 'A/B/C'], and initialRouteName = 'A/B/C'
  // This should result in result = ['A', null,'A/B/C'] where 'A/B' produces
  // the null. In this case, we want to filter out the null and return
  // result = ['A', 'A/B/C'].
  result.removeWhere((Route<dynamic> route) => route == null);
  if (result.isEmpty)
    result.add(navigator._routeNamed<dynamic>(Navigator.defaultRouteName, arguments: null));
  return result;
}