我正在构建一个要检查用户是否已登录的应用程序,否则,我将构建某个小部件树。因此,如果用户的身份验证状态更改,它将重建整个树。因此,您登陆到启动页面,启动页面一直等到它知道您是否已登录,然后返回RegisterPage或GroupManagementPage,这基本上是一个页面,您可以在其中看到所有组,有点像whatsapp,但没有对话,而是有组。问题是我只是不知道如何正确执行此操作。
我正在使用Firebase身份验证,当前要做的是从主应用程序外部始终提供AuthenticationProvider。在我的初始页面中,我在流构建器中使用此提供程序的流(从firebase基本上是onAuthChanged,但映射到AuthenticationCertificate),我等待流激活后再构建其余小部件树。如果流是 Activity 的,则将我的AuthenticationCertificate提供给GroupManagementPage。
这样就可以了,但是导航器出现了问题。因为在MainApp()中,我将初始页面定义为本地路线。因此,现在每当我弹出路线时,我都会回到初始页面,这不是我想要的。我还注意到有些页面没有提供AuthenticationCertificate。我不确定为什么会这样,因为导航器也传递了上下文,但仍必须调查一下。
现在我的问题是如何使它正常工作,以便将AuthenticationCertificate传递给从GroupManagementPage导航到的所有小部件,并且当用户注销时将其返回到RegisterPage?这是正确的方法,我该如何做呢?
主应用程序
return MultiProvider(
providers: [
ChangeNotifierProvider<PreferencesProvider>(
create: (_) => PreferencesProvider()),
Provider<AuthenticationProvider>(create: (_) => AuthenticationProvider(),),
Provider<GroupProvider>(create: (_) => GroupProvider()),
Provider<UserProvider>(
create: (_) => UserProvider(),
),
],
child: Consumer<PreferencesProvider>(
builder: (context, preferences, _) => MaterialApp(
home: TheSplashPage(),
routes: <String, WidgetBuilder>{
TheRegisterPage.routeName: (BuildContext context) =>
TheRegisterPage(),
TheGroupManagementPage.routeName: (BuildContext context) =>
TheGroupManagementPage(),
TheGroupPage.routeName: (BuildContext context) => TheGroupPage(),
TheSettingsPage.routeName: (BuildContext context) =>
TheSettingsPage(),
TheProfilePage.routeName: (BuildContext context) =>
TheProfilePage(),
TheGroupCreationPage.routeName: (BuildContext context) =>
TheGroupCreationPage(),
},
theme: preferences.isDarkMode
? DarkTheme.themeData
: LightTheme.themeData,
debugShowCheckedModeBanner: false,
),
),
);
启动画面
class TheSplashPage extends StatelessWidget {
static const int loadTimeInSeconds = 2;
@override
Widget build(BuildContext context) {
AuthenticationProvider authenticationProvider =
Provider.of<AuthenticationProvider>(context);
return FutureBuilder(
future: Future.delayed(new Duration(seconds: loadTimeInSeconds)),
builder: (context, delaySnapshot) {
return StreamBuilder<UserAuthenticationCertificate>(
stream: authenticationProvider.authenticationStream(),
builder: (context, certificateSnapshot) {
if (delaySnapshot.connectionState != ConnectionState.done &&
certificateSnapshot.connectionState ==
ConnectionState.active) {
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: Center(
child: Text(
'This is the splash page',
style: Theme.of(context).textTheme.body1,
),
),
);
} else {
if (certificateSnapshot.hasData) {
return Provider<UserAuthenticationCertificate>.value(
value: certificateSnapshot.data,
child: TheGroupManagementPage(),
);
} else {
return TheRegisterPage();
}
}
},
);
});
}
}
身份验证提供程序中的流
Stream<UserAuthenticationCertificate> authenticationStream()
{
return _authentication.onAuthStateChanged.map((firebaseUser) => UserAuthenticationCertificate.fromFirebase(firebaseUser));
}
最佳答案
如果要使用Stream,请使用StreamProvider而不是Provider。但我不知道您为什么要在这种情况下使用Stream。为什么不选择ChangeNotifierProvider?
使用Navigator.of(context)
导航到您的页面。您的代码的导航部分很奇怪。您在TheSplashPage()的构建函数中返回TheGroupManagementPage()或TheRegisterPage()。这不是导航器的工作方式。您应该使用Navigatort的方法,例如push
,pop
,pushNamed
等。
Navigator.of(context).pushNamed(TheGroupManagementPage.routeName);
So now whenever I pop a route I go back to the splash page, which is not what I want.
登录后,可以从导航树中删除SplashPage。这是一种方法,不是一个坏方法。验证后推送页面时,应使用
pushReplacement
或pushReplacementNamed
。您也可以将其用于注销,以用RegisterPage()替换导航树。或者,如果您有主屏幕(如启动后的根路由),则您的情况可能是TheGroupManagementPage。然后将 TheGroupManagementPage 包裹在 WillPopScope 中,然后在WillPop 的中进行操作。我更喜欢第一种方法。
关于flutter - 如何为到达页面后的窗口小部件树中的所有窗口小部件提供身份验证证书,并使导航器仍在工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60902932/