在我的应用程序中,我有一个 UserAccountsDrawerHeader 的抽屉,我通过简单地从 FirebaseAuth.instance.currentUser.x 获取x属性来提供其属性
在最新的firebase_auth 0.2.0版本中,currentUser()是异步的 .
我已经尝试了几个小时来存储当前登录用户的信息,但还没有达到正确的方法来执行此操作 .
我知道我可以通过以下方式访问它们:
Future<String> _getCurrentUserName() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
return user.displayName;
}
...
new UserAccountsDrawerHeader(accountName: new Text(_getCurrentUserName()))
我知道这些代码片段会导致类型不匹配,但我只是想说明我想要做什么 .
我到底错过了什么阻止我达成解决方案?
Update
class _MyTabsState extends State<MyTabs> with TickerProviderStateMixin {
TabController controller;
Pages _page;
String _currentUserName;
String _currentUserEmail;
String _currentUserPhoto;
@override
void initState() {
super.initState();
_states();
controller = new TabController(length: 5, vsync: this);
controller.addListener(_select);
_page = pages[0];
}
My method
我只是将auth状态与我之前实现的TabBar状态相结合
_states() async{
var user = await FirebaseAuth.instance.currentUser();
var name = user.displayName;
var email = user.email;
var photoUrl = user.photoUrl;
setState(() {
this._currentUserName=name;
this._currentUserEmail=email;
this._currentUserPhoto=photoUrl;
_page = pages[controller.index];
});
}
My Drawer
drawer: new Drawer(
child: new ListView(
children: <Widget>[
new UserAccountsDrawerHeader(accountName: new Text(_currentUserName) ,
accountEmail: new Text (_currentUserEmail),
currentAccountPicture: new CircleAvatar(
backgroundImage: new NetworkImage(_currentUserPhoto),
),
这是我从调试控制台获得的 exception
I/flutter (14926): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (14926): The following assertion was thrown building MyTabs(dirty, state: _MyTabsState#f49aa(tickers:
I/flutter (14926): tracking 1 ticker)):
I/flutter (14926): 'package:flutter/src/widgets/text.dart': Failed assertion: line 207 pos 15: 'data != null': is not
I/flutter (14926): true.
I/flutter (14926): Either the assertion indicates an error in the framework itself, or we should provide substantially
Update 2:
这就是我从firebase示例中修改google登录功能的方法:
Future <FirebaseUser> _testSignInWithGoogle() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
//checking if there is a current user
var check = await FirebaseAuth.instance.currentUser();
if (check!=null){
final FirebaseUser user = check;
return user;
}
else{
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);
return user;
}
}
Update 3:
我的主要功能
void main() {
runApp(
new MaterialApp(
home: new SignIn(),
routes: <String, WidgetBuilder>{
"/SignUp":(BuildContext context)=> new SignUp(),
"/Login": (BuildContext context)=> new SignIn(),
"/MyTabs": (BuildContext context)=> new MyTabs()},
));
}
然后我的SignIn包含一个按下的谷歌按钮:
onPressed: () { _testSignInWithGoogle(). //async returns FirebaseUser
whenComplete(()=>Navigator.of(context).pushNamed("/MyTabs")
);
}
并且更新1中的抽屉包含在MyTabs构建中 .
2 回答
有几种可能性 .
第一:使用有状态小部件覆盖initState方法,如下所示:
第二:使用FutureBuilder小部件基本上,它是那些不想使用有状态小部件的人的包装器 . 它最终也是如此 . 但是你将无法在其他地方重复使用你的未来 .
说明:您的getCurrentUserName是异步的 . 您不能直接将其与其他同步功能混合使用 . 异步函数非常有用 . 但如果你想使用它们,请记住两件事:
在另一个异步函数中,你可以
var x = await myFuture
,它会等到myFuture
结束才能得到它的结果 .但是你不能在同步功能中使用
await
. 相反,您可以使用myFuture.then(myFunction)
或myFuture.whenComplete(myFunction)
. 未来完成后将调用myFunction
. 并且它们.then
和.whenComplete
都会将您的未来结果作为参数传递给myFunction
.“如何正确实施认证”?你绝对不应该这样做 . 你将有大量的代码重复 .
组织诸如Authentification之类的层的最理想方式是这样的:
然后,当您需要配置或窗口小部件中的当前用户时,您可以这样做:
这样做有很多好处,没有理由不去做 . 如“代码一次,随处使用” . 或者具有通用值并为特定小部件覆盖它的能力 . 你会发现许多Flutter小部件都遵循这个想法 . 如导航,脚手架,主题,......
但"How to do this ??"这都归功于
BuildContext context
参数 . 这提供了一些帮助 . 例如,Authentification.of(context)
的代码如下: