簡體   English   中英

如何創建一個 BlocListener 可以監聽 flutter 中的所有頁面並訪問 MaterialApp 上下文?

[英]How to create a BlocListener that can listen to all pages in flutter with access to MaterialApp context?

我正在嘗試創建一個BlocListener ,它能夠偵聽整個應用程序中的所有頁面/路由,就像您如何在整個應用程序中訪問BlocProvider一樣,如果它們是在根級別定義的,如下面的代碼

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內。 但是,在這種情況下,我需要特定的偵聽器( 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,
    );
  }
}

有沒有不同的方法來解決這個問題?

所以我最終定義了一個

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 之外的情況下進行導航(在我的情況下,通過在 MaterialApp 上方的根級別找到的 AuthListener),我可以通過

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

這意味着我終於可以訪問 MaterialApp 導航器和上下文,即使在 MaterialApp 之外的偵聽器也允許我進行導航和顯示對話框

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM