访问firebase_auth插件版本0.2.0中的currentUser数据

时间:2017-08-22 18:12:08

标签: dart firebase-authentication flutter dart-async

在我的应用中,我有一个带有 UserAccountsDrawerHeader 的抽屉,只需从 FirebaseAuth.instance.currentUser.x 获取x属性即可提供其属性 p>

在最新的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()))

我知道这些代码段会导致类型不匹配,但我只想说明我要做的事情。

我错过了什么,这使我无法达成解决方案?

更新

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];
  }

我的方法

我刚刚将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];
    });
  }

我的抽屉

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),
              ),

以下是我从调试控制台获取的异常

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

更新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;
    }
    }

更新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 个答案:

答案 0 :(得分:2)

有几种可能性。

首先:使用有状态小部件 像这样重写initState方法:

class Test extends StatefulWidget {
  @override
  _TestState createState() => new _TestState();
}

class _TestState extends State<Test> {
  String _currentUserName;

  @override
  initState() {
    super.initState();
    doAsyncStuff();
  }

  doAsyncStuff() async {
    var name = await _getCurrentUserName();
    setState(() {
      this._currentUserName = name;
    });
  }


  @override
  Widget build(BuildContext context) {
    if (_currentUserName == null)
      return new Container();
    return new Text(_currentUserName);
  }
}

第二:使用FutureBuilder小部件 基本上,它是那些不想使用有状态小部件的人的包装器。它最终也是如此。 但是你无法在其他地方重复使用你的未来。

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new FutureBuilder(
      future: _getCurrentUserName(),
      builder: (context, AsyncSnapshot<int> snapshot) {
        if (snapshot.hasData)
          return new Text(snapshot.data.toString());
        else
          return new Container();
      },
    );
  }
}

说明: 您的getCurrentUserName是异步的。 您不能直接将其与其他同步功能混合使用。 异步函数非常有用。但如果你想使用它们,请记住两件事:

在另一个异步函数中,你可以var x = await myFuture,它会等到myFuture完成才能得到它的结果。

但您无法在同步功能中使用await。 相反,你可以使用 myFuture.then(myFunction)myFuture.whenComplete(myFunction)。未来完成后将调用myFunction。他们.then.whenComplete都会将您未来的结果作为参数传递给您的myFunction

答案 1 :(得分:1)

“如何正确实施身份验证”? 你绝对不应该这样做。你将有大量的代码重复。

组织诸如Authentification等层的最理想方式是:

runApp(new Configuration.fromFile("confs.json",
  child: new Authentification(
    child: new MaterialApp(
      home: new Column(
        children: <Widget>[
          new Text("Hello"),
          new AuthentifiedBuilder(
            inRoles: [UserRole.admin],
            builder: (context, user) {
              return new Text(user.name);
            }
          ),
        ],
      ),
    ),
  ),
));

然后,当您需要配置或窗口小部件中的当前用户时,您可以这样做:

@override
Widget build(BuildContext context) {
  var user = Authentification.of(context).user;
  var host = Configuration.of(context).host;
  // do stuff with host and the user
  return new Container();
}

这样做有很多好处,没有理由不去做。 如“代码一次,随处使用”。或者具有通用值并为特定小部件覆盖它的能力。 你会发现许多Flutter小部件都遵循这个想法。 如导航,脚手架,主题......

但“怎么做?” 这完全归功于BuildContext context参数。这提供了一些帮助。 例如,Authentification.of(context)的代码如下:

class Authentification extends StatefulWidget {
    final Widget child;

    static AuthentificationData of(BuildContext context) {
        final AuthentificationData auth = context.inheritFromWidgetOfExactType(AuthentificationData);
        assert(auth != null);
        return auth;
    }

    Authentification({this.child});
    @override
    AuthentificationState createState() => new AuthentificationState();
}