Как создать BlocListener, который может прослушивать все страницы в трепетании с доступом к контексту MaterialApp? - PullRequest
0 голосов
/ 18 апреля 2020

Я пытаюсь создать BlocListener, который имеет возможность прослушивать все страницы / маршруты в приложении так же, как вы можете получить доступ к Bloc или Provider во всем приложении, если они определены на уровне root, как в приведенном ниже коде

runApp(
  MultiProvider(
    providers: [
      ChangeNotifierProvider<IdentityTokenProvider>(
        create: (_) => IdentityTokenProvider(),
      ),
    ],
    child: MultiBlocProvider(
      providers: [
        BlocProvider<AuthBloc>(
          create: (_) => AuthBloc(),
        ),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: AppConfig.DEBUGGABLE,
        theme: ThemeData(
            // fontFamily: CustomFontStyle.montserrat,
            ),
        home: AuthListener(
          child: Center(
            child: const MainApp(),
          ),
        ),
      ),
    ),
  ),
);

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

Моя реализация маршрутизации страниц, которая удаляет стек, что является еще одной причиной потери доступа к AuthListener

Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(builder: (_) => route),
        (Route<dynamic> route) => false);

Почему я удаляю стек маршрута / страницы при переходе к другая страница?

  • Я специально использую это после аутентификации. Вы действительно не хотите, чтобы пользователь мог нажать кнопку «Назад» после входа в систему и перенаправить пользователя обратно на страницу входа, верно? Обычно кнопка «Назад» должна скрывать / закрывать приложение при входе в систему.

Моя AuthListener реализация

class AuthListener extends StatefulWidget {
  final Widget child;

  const AuthListener({Key key, @required this.child}) : super(key: key);

  @override
  _AuthListenerState createState() => _AuthListenerState();
}

class _AuthListenerState extends State<AuthListener> {
  @override
  Widget build(BuildContext context) {
    return BlocListener<AuthBloc, AuthState>(
      listener: (context, state) {
        if (state is AuthAuthenticated) {
          PageRouterController.pushAndRemoveStack(context, const EcomPage());
        } else if (state is AuthUnauthenticated) {
          PageRouterController.pushAndRemoveStack(context, const LoginPage());
        }
      },
      child: widget.child,
    );
  }
}

Есть ли другой способ обойти это?

1 Ответ

0 голосов
/ 19 апреля 2020

Итак, я определил

static final GlobalKey<NavigatorState> navigatorKey = new GlobalKey();

и использовал его в моем MaterialApp

@override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: App.DEBUGGABLE,
      theme: ThemeData(
          // fontFamily: CustomFontStyle.montserrat,
          ),
      navigatorKey: App.navigatorKey,
      home: Center(
        child: const LoginPage(),
      ),
    );
  }

Итак, всякий раз, когда мне приходится перемещаться в случаях, когда реализация находится за пределами MaterialApp (в моем случае через AuthListener, который находится на уровне root над MaterialApp), я могу перемещаться с помощью

App.navigatorKey.currentState.pushAndRemoveUntil(
            MaterialPageRoute(builder: (_) => route),
            (Route<dynamic> route) => false);

, что означает, что я, наконец, могу получить доступ к навигатору и контексту MaterialApp, даже если слушатель за пределами MaterialApp, который позволяет мне выполнять навигацию и показ диалогов

...