Ich arbeite mit dem neuen Firebase-SDK.
Wenn ich die Benutzeranmeldung durchführe, wird die onAuthStateChanged-Methode zweimal mit demselben Status aufgerufen (Benutzeranmeldung usw.).
Ich bin sicher, ich füge den AuthStateListener nur einmal zur FirebaseAuth-Referenz hinzu.
Irgendeine Hilfe?
Ja, und das ist sehr ärgerlich. Dies ist aufgrund eines Registrierungsaufrufs. Darüber hinaus wird onAuthStateChanged in vielen verschiedenen Status mehrmals aufgerufen, ohne dass man wissen kann, um welchen Status es sich handelt.
Dokumentation sagt:
onAuthStateChanged (FirebaseAuth-Authentifizierung)
Diese Methode wird im UI-Thread bei Änderungen des Authentifizierungsstatus aufgerufen:
Gleich nachdem der Listener registriert wurde
Wenn ein Benutzer angemeldet ist
- Wenn der aktuelle Benutzer abgemeldet ist
- Wenn sich der aktuelle Benutzer ändert
- Wenn sich das Token des aktuellen Benutzers geändert hat
Hier einige Tipps, um den aktuellen Stand zu erfahren:
Dieser Listener ist ein Durcheinander und sehr fehleranfällig. Das Firebase-Team sollte sich darum kümmern.
Meine Problemumgehung ist die Verwendung eines global deklarierten Booleschen Befehls, wenn onAuthStateChanged zuvor aufgerufen werden muss.
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;
}
}
}
};
Normalerweise möchte ich die Benutzeroberfläche vor dem Hinzufügen des Listeners einrichten und das Setup jedes Mal wiederholen, wenn sich der Auth-Status ändert (Vermeidung des ersten Doppelrufs). Meine Lösung besteht darin, die Boolesche Flag-Lösung zu verbessern und die UID (nicht das Token) des letzten Benutzers zu verfolgen, die null sein kann.
private FirebaseAuth firebaseAuth;
private String lastUid; // keeps track of login status and changes thereof
In onCreate rufe ich die Auth-Instanz ab und stelle die Benutzeroberfläche entsprechend ein, bevor der Listener in onStart hinzugefügt wird.
@Override
protected void onCreate(Bundle savedInstanceState){
...
firebaseAuth = FirebaseAuth.getInstance();
getUserSetUI();
...
}
wo getUserSetUI setzt lastUid gemäß der Auth-Instanz
private void getUserSetUI(){
lastUid = (firebaseAuth == null || firebaseAuth.getCurrentUser() == null) ?
null : firebaseAuth.getUid();
setUI(!(lastUid == null));
}
Der Listener prüft, ob sich der Status tatsächlich geändert hat
@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();
}
}
Während die anderen hier gegebenen Antworten die Arbeit erledigen könnten, finde ich die Verwaltung einer Flagge umständlich und fehleranfällig.
Ich ziehe es vor, die Veranstaltung innerhalb kurzer Zeit zu entprellen. Es ist sehr unwahrscheinlich, vielleicht sogar unmöglich, dass sich ein Benutzer innerhalb von 200 ms an- und wieder abmeldet.
TLDR
Entprellen bedeutet, dass Sie vor der Bearbeitung eines Ereignisses warten, bis dasselbe Ereignis innerhalb eines festgelegten Zeitraums erneut ausgelöst wird. In diesem Fall setzen Sie den Timer zurück und warten erneut. Wenn nicht, übernehmen Sie das Ereignis.
Dies ist eine Android Frage, die nicht mein Fachgebiet ist, aber ich bin mir sicher Android bietet eine Art Tool, das bei der Aufgabe helfen kann. Wenn nicht können Sie eine mit einem einfachen Timer machen.
So könnte eine Javascript-Implementierung aussehen:
var debounceTimeout;
const DebounceDueTime = 200; // 200ms
function onAuthStateChanged(auth)
{
if (debounceTimeout)
clearTimeout(debounceTimeout);
debounceTimeout = timeout(() =>
{
debounceTimeout = null;
handleEvent(auth);
}, DebounceDueTime);
}
function handleAuthStateChanged(auth)
{
// ... process event
}