Перенаправить пользователя с именованного маршрута - PullRequest
0 голосов
/ 28 февраля 2020

Таким образом, у меня есть проблема, аналогичная той, которая задала этот старый вопрос , за исключением тех требований, с которыми ни один из ответов не помог.

Когда пользователь открывает приложение, Я хочу, чтобы их приветствовали со страницей входа в систему, если они не вошли в систему, или домашней страницей (вид нижней навигационной панели), если они это сделали. Я могу определить это в MaterialApp следующим образом:

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

Пока все хорошо. За исключением того, что я хочу, чтобы это работало в Интернете, и теперь, хотя экран по умолчанию, когда пользователь впервые открывает myapp.com, равен myapp.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 вместо простого нажатия, нажатие назад откроет пустой экран (вместо закрытия приложения).

Есть ли способ сделать это правильно, чтобы он работал как в Интернете, так и на мобильных устройствах

1 Ответ

1 голос
/ 28 февраля 2020

Если вы используете миксин RouteAware в ваших классах виджетов, они будут уведомлены, когда они будут перемещены (или удалены). Вы можете использовать это, чтобы проверить, должен ли пользователь быть там, и отойти от него, если его нет:

Чтобы использовать его, сначала вам нужен глобальный экземпляр 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');
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...