首页 > 解决方案 > 从命名路由重定向用户

问题描述

所以我和问这个老问题的人有一个类似的问题,除了有不同的要求,那里的答案都没有帮助。

当用户打开应用程序时,如果他们没有登录,我希望他们看到登录页面,或者如果他们登录了主页(底部导航栏视图)。我可以定义MaterialApp如下:

MaterialApp(
  initialRoute: authProvider.isAuthenticated
      ? '/home'
      : '/login',
  routes: {
    '/home': (_) =>
        ChangeNotifierProvider<BottomNavigationBarProvider>(
            child: AppBottomNavigationBar(),
            create: (_) => BottomNavigationBarProvider()),
    '/login': (_) => LoginView()
  },
)

到目前为止,一切都很好。除了我想让它在网络上工作,现在即使用户第一次打开时的默认屏幕myapp.commyapp.com/#/login,任何用户都可以通过简单地访问来绕过登录屏幕myapp.com/#/home

现在我尝试将用户重定向initState()到底部导航栏的登录页面(并将 设置initialRoute/home),但在移动设备上这有不良行为。

如果我试试这个:

void initState() {
  super.initState();

  if (!Provider.of<AuthProvider>(context, listen: false).isAuthenticated) {
    SchedulerBinding.instance.addPostFrameCallback((_) {
      Navigator.of(context).pushNamed('/login');
    });
  }
}

然后只需按返回即可将用户返回到主页,再次绕过登录。如果我尝试使用popAndPushNamed而不是仅仅按下,按下返回将打开一个空白屏幕(而不是关闭应用程序)。

有什么方法可以正确地做到这一点,以便它可以在网络和移动设备上运行?

标签: flutterdartflutter-webmobile-development

解决方案


如果您RouteAware在小部件类上使用 mixin,它们将在导航到(或离开)时收到通知。您可以使用它来检查用户是否应该在那里,如果他们不应该在那里,则将他们导航开:

要使用它,首先您需要RouteObserver所有小部件类都可以访问的全局实例:

final routeObserver = RouteObserver<PageRoute>();

然后你需要用你的注册它MaterialApp

MaterialApp(
  routeObservers: [routeObserver],
)

然后将您的小部件注册到路由观察器:

class HomeViewState extends State<HomeView> with RouteAware {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  void didPop() {
    // This gets called when this widget gets popped
  }

  void didPopNext() {
    // This gets called when another route gets popped making this widget visible
  }

  void didPush() {
    // This gets called when this widget gets pushed
  }

  void didPushNext() {
    // This gets called with another widget gets pushed making this widget hidden
  }

  ...
}

在您的情况下,如果用户错误地进入该页面,您可以使用该didPush路由将用户导航到登录页面:

void didPush() {
  if (checkLoginStateSomehow() == notLoggedIn) {
    Navigator.of(context).pushReplacementNamed('login');
  }
}

推荐阅读