如何创建一个可以通过访问 MaterialApp 上下文来监听所有页面的 BlocListener?
How to create a BlocListener that can listen to all pages in flutter with access to MaterialApp context?
我正在尝试创建一个 BlocListener
,它能够在整个应用程序中收听所有 pages/routes,就像您可以访问 Bloc
或 [=15] 一样=] 如果它们像下面的代码一样在根级别定义,则贯穿整个应用程序
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
中,因为它包含使用页面导航的代码(如果实现完成 outside/above MaterialApp
) 的小部件树,并使我们使用 MaterialApp
上下文来显示对话框。
我的页面路由实现删除了堆栈,这是无法访问 AuthListener
的另一个原因
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (_) => route),
(Route<dynamic> route) => false);
为什么我在移动到另一个页面时要删除 route/page 堆栈?
- 我是专门认证后用这个的。您真的不希望用户在登录后能够按后退按钮,然后将用户重定向回登录页面吗?通常后退按钮应该 hide/close 应用程序在登录时。
我的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 之外的侦听器也允许我进行导航和显示对话框
我正在尝试创建一个 BlocListener
,它能够在整个应用程序中收听所有 pages/routes,就像您可以访问 Bloc
或 [=15] 一样=] 如果它们像下面的代码一样在根级别定义,则贯穿整个应用程序
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
中,因为它包含使用页面导航的代码(如果实现完成 outside/above MaterialApp
) 的小部件树,并使我们使用 MaterialApp
上下文来显示对话框。
我的页面路由实现删除了堆栈,这是无法访问 AuthListener
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (_) => route),
(Route<dynamic> route) => false);
为什么我在移动到另一个页面时要删除 route/page 堆栈?
- 我是专门认证后用这个的。您真的不希望用户在登录后能够按后退按钮,然后将用户重定向回登录页面吗?通常后退按钮应该 hide/close 应用程序在登录时。
我的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 之外的侦听器也允许我进行导航和显示对话框