Firebase Android onAuthStateChanged 调用了两次
Posted
技术标签:
【中文标题】Firebase Android onAuthStateChanged 调用了两次【英文标题】:Firebase Android onAuthStateChanged called twice 【发布时间】:2016-10-07 00:24:09 【问题描述】:我已经开始使用新的 Firebase SDK。
当我进行用户登录时,我的 onAuthStateChanged 方法被调用了两次,状态相同(等用户登录)。
我确定我只将 AuthStateListener 添加到 FirebaseAuth 参考中一次。
有什么帮助吗?
【问题讨论】:
你的代码在哪里? 我的代码中也存在这个问题。onStart()
除了调用 super:FirebaseAuth.getInstance().addAuthStateListener(this);
之外只有这个代码。在其他任何地方都找不到这个调用,我检查了onStart()
只被调用了一次。然而,onAuthStateChanged(...)
方法被调用了两次(有时是三次)。
可能是一个错误,同时在此答案中使用标志:***.com/a/37686371/3597165
Firebase android onAuthStateChanged() fire twice after signInWithEmailAndPassword()的可能重复
9.4.0 中未修复
【参考方案1】:
虽然此处提供的其他答案可能会完成这项工作,但我发现管理标志很麻烦且容易出错。
我更喜欢在短时间内消除事件的抖动。假设用户在 200 毫秒内登录然后注销是非常不可能的,甚至是不可能的。
TLDR
去抖动意味着在处理事件之前,您等待查看相同的事件是否会在预定义的时间段内再次触发。 如果确实如此,则重置计时器并再次等待。 如果没有,则由您处理该事件。
这是一个 Android 问题,不是我的领域,但我确信 android 提供了某种可以帮助完成任务的工具。 如果没有,您可以使用一个简单的计时器制作一个。
以下是 javascript 实现的样子:
var debounceTimeout;
const DebounceDueTime = 200; // 200ms
function onAuthStateChanged(auth)
if (debounceTimeout)
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(() =>
debounceTimeout = null;
handleAuthStateChanged(auth);
, DebounceDueTime);
function handleAuthStateChanged(auth)
// ... process event
【讨论】:
最佳解决方案恕我直言。希望我在写 if else 阶梯之前看到这个答案。哎呀。【参考方案2】: try
FirebaseAuth.getInstance().signOut();
FirebaseInstanceId.getInstance().deleteInstanceId();
catch (Exception ex)
ex.printStackTrace();
当用户从 gmail 注销时,该用户也应该从 firebase 注销。这就是我解决此问题的方法。
【讨论】:
【参考方案3】:if (authStateListener == null)
authStateListener = new FirebaseAuth.AuthStateListener()
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth)
if (firebaseAuth.getCurrentUser() == null)
//Do anything here which needs to be done after signout is complete
FirebaseAuth.getInstance().removeAuthStateListener(this);
Log.d(TAG_, "logout");
finish();
else
;
应调用 FirebaseAuth.getInstance().removeAuthStateListener(this)
【讨论】:
【参考方案4】:通常我想在添加侦听器之前设置 UI,并随时重复设置身份验证状态更改(避免初始双重调用)。我的解决方案是增强布尔标志解决方案并跟踪最后一个用户的 uid(不是令牌),它可能为 null。
private FirebaseAuth firebaseAuth;
private String lastUid; // keeps track of login status and changes thereof
在 onCreate 中,我获取 auth 实例并相应地设置 UI,然后在 onStart
中添加侦听器@Override
protected void onCreate(Bundle savedInstanceState)
...
firebaseAuth = FirebaseAuth.getInstance();
getUserSetUI();
...
其中 getUserSetUI 根据 auth 实例设置 lastUid
private void getUserSetUI()
lastUid = (firebaseAuth == null || firebaseAuth.getCurrentUser() == null) ?
null : firebaseAuth.getUid();
setUI(!(lastUid == null));
监听器检查状态是否真的改变了
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth auth)
String uid = auth.getUid(); // could be null
if( (uid == null && lastUid != null) || // loggedout
(uid != null && lastUid == null) || // loggedin
(uid != null && lastUid != null && // switched accounts (unlikely)
!uid.equals(lastUid)))
getUserSetUI();
【讨论】:
【参考方案5】:我的解决方法是使用全局声明的布尔值来标记是否需要调用 onAuthStateChanged。
private Boolean authFlag = false;
mAuthListener = new FirebaseAuth.AuthStateListener()
@Override
public void onAuthStateChanged(@NonNull final FirebaseAuth firebaseAuth)
if (firebaseAuth.getCurrentUser() != null)
if(authFlag== false)
// Task to perform once
authFlag=true;
;
【讨论】:
谢谢简单,但当您不想浪费更多时间时,可以完成工作。【参考方案6】:是的,这很烦人。这是由于注册电话。不仅如此,onAuthStateChanged 还会在许多不同的状态下被多次调用,不可能知道它是哪个状态。
Documentation 说:
onAuthStateChanged(FirebaseAuth 身份验证)
当身份验证状态发生变化时,会在 UI 线程中调用此方法:
在监听器注册之后
当用户登录时
当前用户退出时
当当前用户改变时
当当前用户的令牌发生变化时
这里有一些发现当前状态的提示:
注册调用:跳过带有标志的第一个调用。 用户已登录:参数中的用户为 != null。 用户已退出:参数中的用户为 == null。 当前用户更改:参数中的用户为 != null 且最后一个用户 ID 为 != 参数中的用户 ID 用户令牌刷新:参数中的用户为 != null 且最后一个用户 ID 为 == 参数中的用户 ID这个监听器很乱而且很容易出错。 Firebase 团队应该调查一下。
【讨论】:
我同意。此问题目前存在于 ios 上。感谢您为我们整理状态。 即使过了将近 5 年,问题依然存在......以上是关于Firebase Android onAuthStateChanged 调用了两次的主要内容,如果未能解决你的问题,请参考以下文章