什么用例有 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()
用于更新易于更改的用户数据,例如displayName
、photoUrl
、isEmailVerified
等,仅此而已,作为其他数据,例如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] 然后再补水 更改您的应用程序。
这也包括.isEmailVerified
afaik(编辑:可能不是真的,见 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() 功能?的主要内容,如果未能解决你的问题,请参考以下文章
在 Keycloak 中使用 OpenID Connect 的两个用例有啥区别? (客户端与应用程序)
CollectionViewSource、ICollectionView、ListCollectionView、IList 和 BindingListCollectionView 及其用例有啥区别?