Flutter 使用Firebase的声明性身份验证路由

Flutter 使用Firebase的声明性身份验证路由,flutter,Flutter,当用户登录或注销时,我使用流来监听登录和注销事件,而不是使用Navigator.push推送用户 StreamProvider.value( 值:FirebaseAuth.instance.onAuthStateChanged, ) 它对home route非常有用,因为如果用户仍然经过身份验证,它会立即处理登录 消费者( 生成器:(uu,用户,uu){ final isLoggedIn=user!=null; 返回材料PP( 主页:isLoggedIn?主页():AuthPage(), //

当用户登录或注销时,我使用流来监听登录和注销事件,而不是使用
Navigator.push推送用户

StreamProvider.value(
值:FirebaseAuth.instance.onAuthStateChanged,
)
它对home route非常有用,因为如果用户仍然经过身份验证,它会立即处理登录

消费者(
生成器:(uu,用户,uu){
final isLoggedIn=user!=null;
返回材料PP(
主页:isLoggedIn?主页():AuthPage(),
// ...
);
},
);
然而,这只是回家的路线。例如,如果用户随后导航到一个设置页面,在该页面中单击一个按钮进行注销,则不会有程序性的注销和再次跳转到auth屏幕。我要么说
Navigator.of(context).pushName和removeUntil('/auth',(\u)=>false)
,要么得到一个关于
user
为空的错误

这是有道理的。我只是在寻找另一种可能的方式,当他们注销时,我不必自己做任何堆栈管理

通过将
builder
属性添加到
MaterialApp

builder:(\uux,小部件){
返回isLoggedIn?小部件:AuthPage();
},

这在我未经身份验证后成功地将我移动到了auth页面,但事实证明,
widget
实际上是导航器。这意味着当我返回到
AuthPage
时,我无法调用任何依赖于父导航器的内容。

这是怎么回事,你用这个小部件包装依赖于这个流的所有屏幕,它对你隐藏了监听流并相应更新的逻辑(你应该像你在问题中所做的那样提供流):

然后,您可以在从其他页面推送时使用它,如下所示:

Navigator.of(context).pushReplacement(MaterialPageRoute(
        builder: (ctx) => AuthDependentWidget(
              childWidget: SettingsScreen(),//or any other screen that should listen to the stream
            )));

我找到了一个方法来实现这一点(爱的伟大答案仍然是完全有效的),以防其他人在这个问题上采取行动:

您需要利用嵌套的导航器。
Root
将是内部导航器,外部导航器由
MaterialApp
创建:

return MaterialApp(
home:isLoggedIn?Root():AuthPage(),
路线:{
Root.routeName:()=>Root(),
AuthPage.routeName:(\u)=>AuthPage(),
},
);
您的
根目录
将保留授权用户的导航

类根扩展StatefulWidget{
静态常量字符串routeName='/root';
@凌驾
_RootState createState()=>\u RootState();
}
类_RootState扩展了状态{
最终_appNavigatorKey=GlobalKey();
@凌驾
小部件构建(构建上下文){
返回式示波器(
onWillPop:()异步{
final canPop=_appNavigatorKey.currentState.canPop();
如果(canPop){
wait_appNavigatorKey.currentState.maybePop();
}
回来!坎普;
},
孩子:领航员(
initialRoute:HomePage.routeName,
OnGeneratorOute:(路由设置路由设置){
返回物料管理路线(生成器:(){
交换机(routeSettings.name){
案例首页.routeName:
返回主页();
关于page.routeName的案例:
返回约页();
案例术语UsePage.routeName:
返回TermsOfUsePage();
案例设置SPAGE.routeName:
返回设置spage();
案例EditorPage.routeName:
返回EditorPage();
违约:
抛出“未知路由${routeSettings.name}”;
}
});
},
),
);
}
}

现在,您可以在设置页面(或任何其他页面)内取消身份验证(
FirebaseAuth.instance.signout()
)然后立即跳转到身份验证页面,而无需调用
Navigator
方法。

像第一个屏幕那样用
Consumer
包装您的设置屏幕并不适合您?我的意思是在SettingPage.dart:
isLoggedIn中类似的内容?SettingPage():AuthPage()
你好,亲爱的,这是一种方法,但我必须对每条路线都这样做不?假设我有一个关于页面或验证电子邮件页面,等等。谢谢爱,我现在肯定会用这个。我仍然很好奇,是否有一种方法可以在树的更高的位置进行导航,但我喜欢你的方法。刚刚经过这个,你能解释一下自动导航是如何进行的吗?请提供更多的代码
Navigator.of(context).pushReplacement(MaterialPageRoute(
        builder: (ctx) => AuthDependentWidget(
              childWidget: SettingsScreen(),//or any other screen that should listen to the stream
            )));