什么用例有 FirebaseUser 的 reload() 功能?

Posted

技术标签:

【中文标题】什么用例有 FirebaseUser 的 reload() 功能?【英文标题】:What use case has the reload() function of a FirebaseUser in flutter? 【发布时间】:2019-01-13 12:54:06 【问题描述】:

FirebaseUser 中的 .reload() 方法用于什么? 在本地,该函数不会更改任何数据,并且使用 Firestore.instance.currentUser() 我将始终获取当前数据,不是吗?

来自文档:

公共任务重载() 手动刷新当前用户的数据(例如,附加的提供者、显示名称等)。

所以我最初认为在调用 user.reload() 后输出将是:“用户名:bar”而不是“用户名:foo”。 所以对我来说它似乎并没有做任何事情?

相关的问题: 这也意味着我总是必须调用 FirebaseAuth.instance.currentUser() 以确保必须了解用户的当前信息?没有办法拥有一个 FirebaseUser 流,当用户信息发生变化时它会发出一个新的 FirebaseUser? (我不是指 Firebase.instance.onAuthStateChanged() )

示例:

 static ***Problem() async 
    FirebaseUser user = await FirebaseAuth.instance.currentUser();
    print("Name of User: $user.displayName"); //prints foo

    //Renaming the name from "foo" to "bar"
    UserUpdateInfo userInfo = UserUpdateInfo();
    userInfo.displayName = "bar";
    await _auth.updateProfile(userInfo);

    print("\nBefore calling user.reload:");
    print("Name of user: $user.displayName"); //prints foo
    print("Name of FirebaseAuth.instance.currentUser: $(await FirebaseAuth.instance.currentUser()).displayName"); //prints bar

    await user.reload();

    print("\nAfter calling user.reload:");
    print("Name of user: $user.displayName"); //prints foo
    print("Name of FirebaseAuth.instance.currentUser: $(await FirebaseAuth.instance.currentUser()).displayName"); //prints bar
  

控制台输出:

I/flutter (19989): Name of User: Foo
I/flutter (19989): 
I/flutter (19989): Before calling user.reload:
I/flutter (19989): Name of user: Foo
I/flutter (19989): Name of FirebaseAuth.instance.currentUser: bar
I/flutter (19989): 
I/flutter (19989): After calling user.reload:
I/flutter (19989): Name of user: Foo
I/flutter (19989): Name of FirebaseAuth.instance.currentUser: bar

【问题讨论】:

回答reload() 应该如何在下面工作。我不确定为什么在您的情况下,第二个打印仍然显示旧用户名。我希望其他人发现那里的问题。 所以我的理论应该如何工作是正确的,但实现可能不正确? 【参考方案1】:

让您无需注销即可验证电子邮件,然后再次登录。但它可能是一个错误,但是当你调用 user.reload() 时,你必须再次调用 currentUser()。

这不起作用:

await user.reload();
user.isEmailVerified => still false

你需要:

await user.reload();
user = await _auth.currentUser();
user.isEmailVerified => now it is true

【讨论】:

用户 = _auth.currentUser;为我工作。谢谢。【参考方案2】:

调用User.reload() 会从服务器重新加载该用户的配置文件数据。

当您send an email to the user to verify their email address 时,这是一个典型的用例。当用户单击该电子邮件中的链接时,它会返回到 Firebase 身份验证服务器,该服务器会将其电子邮件地址标记为已验证。但是当这种情况发生时,您的应用程序无法知道它,因为调用直接从电子邮件客户端发送到服务器。通常你会在链接中添加一个所谓的continue URL,它可以在验证电子邮件地址后回调到你的应用程序中。然后您的应用可以调用reload() 从服务器加载更新的状态。

【讨论】:

感谢您的解释。好的,所以user.reload() 用于更新易于更改的用户数据,例如displayNamephotoUrlisEmailVerified 等,仅此而已,作为其他数据,例如uid 是不变的吗?所以它比仅仅获得一个新用户更好,因为它稍微节省了带宽?因为在您的示例中,也可能只是请求currentUser() 而不是调用reload(),对吗? 如果用户已经登录,请求auth.currentUser() 不会从服务器刷新他们的个人资料数据。 啊,好吧,我不知道,谢谢。但是为什么在我的示例中它似乎以这种方式工作?我的意思是第一个Name of FirebaseAuth.instance.currentUser: 应该是“foo”而不是“bar”,如果auth.currentUser() 没有刷新配置文件数据,因为我还没有调用user.reload(),不是吗?【参考方案3】:

这似乎是预期的行为。

就像已经说过的那样,只调用 .reload 是行不通的。

await user.reload();
print(user.emailVerified) // false

相反,您还必须再次获取currentUser

await user.reload();
// `currentUser` is synchronous since FirebaseAuth rework
user = firebaseAuth.currentUser;
print(user.emailVerified) // true

随着返工 (firebase_auth: ^0.18.0) FirebaseAuth 也确实暴露了 .userChanges()-Stream。 这似乎是首选的解决方案,而不是手动重新加载用户信息。

来自FirebaseAuth.userChanges()的文档:

这是 [authStateChanges] 和 [idTokenChanges] 的超集。它 提供有关所有用户更改的事件,例如凭据何时更改 链接、取消链接以及何时更新用户配置文件。这 此 Stream 的目的是收听实时更新 用户无需手动调用 [reload] 然后再补水 更改您的应用程序。

这也包括.isEmailVerifiedafaik(编辑:可能不是真的,见 cmets)。

firebaseAuth.userChanges().listen((user) 
  // Your logic
);

【讨论】:

当我验证电子邮件时,userChanges() 不会触发。但是,user.reload() 返回 emailVerified = true。 @bounxye 对我来说也一样。我必须使用 user.reload() 也许我们做错了什么?【参考方案4】:

这不是错误,但 Firebase Auth 的工作方式很奇怪,他们说它现在不会改变,所以我做了一个包来解决这个问题,在这里获取它:firebase_user_stream

在自述文件中,我解释了问题以及软件包如何解决这些问题,还有示例等等,享受吧!

【讨论】:

【参考方案5】:

也许你需要使用 .then 或 whenComplete 来获取最新的内容,例如:

await _auth.updateProfile().then((retornedValueFromTheMethod) 
  print(retornedValueFromTheMethod);
).whenComplete(() 
  print("TODO something if you want");
);

你需要 updateProfile 是Future<retornedValueType> updateProfile() ...

【讨论】:

await 和 whenComplete 在一个表达式中 - 不是一个好主意

以上是关于什么用例有 FirebaseUser 的 reload() 功能?的主要内容,如果未能解决你的问题,请参考以下文章

xcode 8 执行 UI 测试用例有啥命令吗?

在 Keycloak 中使用 OpenID Connect 的两个用例有啥区别? (客户端与应用程序)

实际项目中的GUI测试用例有多详细?

CollectionViewSource、ICollectionView、ListCollectionView、IList 和 BindingListCollectionView 及其用例有啥区别?

测试用例

测试用例