将 FirebaseUser 映射到自定义用户对象

Posted

技术标签:

【中文标题】将 FirebaseUser 映射到自定义用户对象【英文标题】:Map FirebaseUser to custom User object 【发布时间】:2020-10-01 03:30:04 【问题描述】:

我有一个 Flutter 应用程序,我在其中使用 StreamProvider 监听来自 Firebase 的身份验证更改以显示正确的屏幕。我想做的是将 FirebaseUser 映射到自定义 User 对象,该对象将从 Firestore 中检索,以便从小部件树中的任何位置访问它。

有什么方法可以实现吗?

我现在在做什么:

class AuthService 
  final FirebaseAuth _auth = FirebaseAuth.instance;

  Stream<FirebaseUser> get user 
    return _auth.onAuthStateChanged;
  


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return StreamProvider<FirebaseUser>.value(
      value: AuthService().user,
      child: MaterialApp(...)

【问题讨论】:

创建 models 以将数据转换为 Dart 对象,并且您正在使用 Provider 进行状态管理,因此只需使用 ChangeNotifier 扩展模型并获取数据从任何时候你想:D 想知道您是否找到了解决方案! @Karen 很遗憾没有,这是一个被搁置的小项目^^ 不用担心,我花了几天几夜终于弄明白了。我会写一个解决方案来帮助其他人,如果你重新访问你的项目 【参考方案1】:

首先,从自定义模型开始,决定你想要什么,在这种情况下,我将简单地拥有 uid

###用户模型###

 class CurrentUser 
      final String uid;
    
      CurrentUser ( this.uid );
    

###AuthService###

// Create user object based on FirebaseUser
  CurrentUser _customModelForFirebaseUser(User user) 
    return user != null ? CurrentUser (uid: user.uid) : null;
  

  // auth changed user stream
  Stream<CurrentUser > get user 
    return _auth.onAuthStateChanged
      .map(_customModelForFirebaseUser)
  

###我的应用###

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return StreamProvider<CurrentUser >.value(
      value: AuthService().user,
      child: MaterialApp(
        home: Wrapper(),
      ),
    );
  

然后你可以从任何地方访问它,像这样:

 @override
      Widget build(BuildContext context) 
    
        final user = Provider.of<CurrentUser>(context);

【讨论】:

我明白,但我的用户模型是根据给定 Firebase UID 的 Firestore 查询结果构建的。如何做到这一点,以便当身份验证状态发生变化时,流被映射到某个异步值? 您可以在身份验证发生更改时使用 if/else 进行检查,例如,if (user == null) else map (stream) 尝试 AuthService 中的代码会产生错误“'User' 类没有默认构造函数。尝试使用 'User' 中定义的命名构造函数之一”如何解决这样的问题错误。提前谢谢你。 好吧,你不能再使用User,因为这是 Firebase 服务中的默认类型。 User 以前是FirebaseUser,所以现在只需更改名称即可。【参考方案2】:

我使用https://pub.dev/packages/rxdart 来合并和合并 Firebase 身份验证用户和 Firestore 用户流。

对于身份验证流,我使用userChanges() 来收听所有用户更新。 flatMap() 获取 auth 流,将其转换为 firestore 流并将其与 firestore 流结合,因此现在我们正在监听 auth 更改和 firestore 更改。

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return StreamProvider<UserModel>.value(
      value: FirebaseAuth.instance.userChanges().flatMap(
          (firebaseUser) => DatabaseService(uid: firebaseUser.uid).userData)),
      child: MaterialApp(...)

database.dart

class DatabaseService 
    final String uid;
    DatabaseService(this.uid);

    // get firestore user stream and convert each item into your user object (UserModel in my example)
    Stream<UserModel> get userData 
        return FirebaseFirestore.instance.collection('users').doc(uid).snapshots()
            .map((snapshot) => UserModel.fromMap(snapshot.data()));

user_model.dart

class UserModel 
    String field1;
    String field2;
    UserModel(this.field1, this.field2);

    // using factory to create an instance of UserModel
    factory UserModel.fromMap(Map data) 
        return UserModel(field1: data['field1'], field2: data['field2']);
    

【讨论】:

以上是关于将 FirebaseUser 映射到自定义用户对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 RKMappingOperation 将本地 NSDictionary 映射到自定义对象?

使用敲除映射插件将深度层次化的对象映射到自定义类

Ninja 框架端点在尝试将 JSON 映射到自定义对象时抛出 500 错误

将数据库参数字段值映射到自定义名称

实体框架 - 您能否将导入的存储过程的结果类型映射到自定义实体类型?

Swift 3、RxAlamofire 和映射到自定义对象