如何正确设置基于身份验证的导航



我一直在尝试根据FirebaseAuth的值找出设置应用程序导航的正确方法(即:仅在用户登录后导航)

所以我创建了一个场景,我有 3 个类,我将首先列出我的测试用例,然后讨论我最后面临的问题。

User类是我应用程序中的第一页,它在检查是否有currentUser后绘制它是小部件

class User extends StatefulWidget {
@override
_UserState createState() => new _UserState();
}
class _UserState extends State<User> {
FirebaseUser _user;

@override
initState() {
super.initState();
_checkUser();
}
@override
Widget build(BuildContext context) {
return _user == null? new SignInPage(): new HomePage();
}
_checkUser ()async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
setState((){
this._user = user;
});
}
}

当应用首次启动时,它会加载SignInPage因为没有用户数据:

class SignInPage extends StatefulWidget {
@override
_SignInPageState createState() => new _SignInPageState();
}
class _SignInPageState extends State<SignInPage> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = new GoogleSignIn();

_handleSignIn() async{
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final FirebaseUser user = await _auth.signInWithGoogle(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
assert(user.email != null);
assert(user.displayName != null);
assert(!user.isAnonymous);
assert(await user.getToken() != null);
print (user);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Sign In"),
centerTitle: true,
leading: new Container(),
backgroundColor: new Color.fromARGB(255,17,165,137)),
body: new Container(
child: new Center(
child:
new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[new RaisedButton(
child: new Container(
child: new Row(children: <Widget>[
new Container(
child: new Image(
image: new NetworkImage(
"https://maxcdn.icons8.com/Share/icon/Logos//google_logo1600.png"),
),
margin: new EdgeInsets.only(right: 8.0)),
new Text("Login with Google", style: new TextStyle(color: Colors.redAccent)),
], mainAxisAlignment: MainAxisAlignment.center)),
onPressed: (){_handleSignIn().whenComplete((){Navigator.of(context).pushNamed("/Home");});}
,color: Colors.white),
],),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
)

],
)
)
)
);
}

}

这是我的HomePage类,只有在身份验证经过验证后才能访问;我的主页在中心包含一个RaisedButton,并且具有当前用户的displayNameText子级,以及调用_signOut()方法并返回到SignInageonPressed()操作

final GoogleSignIn _googleSignIn = new GoogleSignIn();

class HomePage extends StatefulWidget {
@override
_HomePageState createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
FirebaseUser _currentUser;
initState() {
super.initState();
_myUser();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Hello:)"),
),
body: new Center(
child: new RaisedButton(child: new Text(_currentUser.displayName),
onPressed: (){_signOut().whenComplete((){Navigator.of(context).pushNamed("/SignInPage");});})
),
);
}
_signOut() async {
await FirebaseAuth.instance.signOut();
await _googleSignIn.signOut();
return "Signed out";
}
_myUser()async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
setState((){
this._currentUser = user;
});
}

}

问题:

  1. 当应用程序首次启动时,它会正常加载SignInPage,但是当我成功登录我的 google 帐户时,它会冻结而没有导航我,因为displayName was called on Null,据我了解 Flutter 没有足够的时间在导航发生之前准备用户数据,我猜测这是因为第 2 点和第 3 点中发生的事情。

  2. 重新启动应用并保留上一个身份验证会话时,应用将自动从Home页面启动,并且显示名称会正确显示。

  3. 在同一会话中,我单击注销并正确导航回SignInPageRaisedButton,我尝试再次登录,我们又回到了主要问题,它试图在获得displayName之前将我导航到我的Home

这就是我理解问题的方式,那么我在这里做错了什么以及如何设计正确的流程?

PS:我想这样做的原因是我想在我的HomePage中使用一些currentUser数据。

更新:

控制台将打印以下内容:

'package:test/SignInScreen.dart': Failed assertion: line 26: 'user.email != null': is not true.

这是在_handleSignInassert声明中。

我也尝试创建一个预主页,发生了同样的问题,我不确定现在出了什么问题。

我建议使用带有FirebaseAuth.instance.currentUser()FutureBuilder作为future参数。然后在您的builder方法中,如果AsyncSnapshothasData属性为 false,则您知道小部件仍在加载,您应该显示一个占位符。Future完成后,可以使用AsyncSnapshotdata属性获取FirebaseUser

或者,您可以在build方法中检查_currentUser是否为 null,并返回一个空容器,因为用户信息尚不可用。

相关内容

  • 没有找到相关文章

最新更新