From 48e2fcc4f2c19d4bb448eeacfde0bede9c869885 Mon Sep 17 00:00:00 2001 From: Matt Jeanes Date: Thu, 27 Oct 2016 11:53:59 -0400 Subject: [PATCH 1/7] Fix passedUser not being used, make it more clear what user is being used --- .../io/fullstack/firestack/FirestackAuth.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/android/src/main/java/io/fullstack/firestack/FirestackAuth.java b/android/src/main/java/io/fullstack/firestack/FirestackAuth.java index 29a4efb..77a997d 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackAuth.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackAuth.java @@ -68,7 +68,7 @@ public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { WritableMap msgMap = Arguments.createMap(); msgMap.putString("eventName", "listenForAuth"); - if (user != null) { + if (FirestackAuthModule.this.user != null) { WritableMap userMap = getUserMap(); msgMap.putBoolean("authenticated", true); @@ -107,8 +107,8 @@ public void createUserWithEmail(final String email, final String password, final @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { - user = task.getResult().getUser(); - userCallback(user, onComplete); + FirestackAuthModule.this.user = task.getResult().getUser(); + userCallback(FirestackAuthModule.this.user, onComplete); }else{ userErrorCallback(task, onComplete); } @@ -125,8 +125,8 @@ public void signInWithEmail(final String email, final String password, final Cal @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { - user = task.getResult().getUser(); - userCallback(user, callback); + FirestackAuthModule.this.user = task.getResult().getUser(); + userCallback(FirestackAuthModule.this.user, callback); } else { userErrorCallback(task, callback); } @@ -156,8 +156,8 @@ public void onComplete(@NonNull Task task) { Log.d(TAG, "signInAnonymously:onComplete:" + task.isSuccessful()); if (task.isSuccessful()) { - user = task.getResult().getUser(); - anonymousUserCallback(user, callback); + FirestackAuthModule.this.user = task.getResult().getUser(); + anonymousUserCallback(FirestackAuthModule.this.user, callback); }else{ userErrorCallback(task, callback); } @@ -176,8 +176,8 @@ public void signInWithCustomToken(final String customToken, final Callback callb public void onComplete(@NonNull Task task) { Log.d(TAG, "signInWithCustomToken:onComplete:" + task.isSuccessful()); if (task.isSuccessful()) { - user = task.getResult().getUser(); - userCallback(user, callback); + FirestackAuthModule.this.user = task.getResult().getUser(); + userCallback(FirestackAuthModule.this.user, callback); } else { userErrorCallback(task, callback); } @@ -356,7 +356,7 @@ public void onComplete(@NonNull Task task) { @ReactMethod public void signOut(final Callback callback) { FirebaseAuth.getInstance().signOut(); - user = null; + this.user = null; WritableMap resp = Arguments.createMap(); resp.putString("status", "complete"); @@ -368,11 +368,11 @@ public void signOut(final Callback callback) { public void getCurrentUser(final Callback callback) { mAuth = FirebaseAuth.getInstance(); - user = mAuth.getCurrentUser(); - if(user == null){ + this.user = mAuth.getCurrentUser(); + if(this.user == null){ noUserCallback(callback); }else{ - userCallback(user, callback); + userCallback(this.user, callback); } } @@ -387,8 +387,8 @@ public void googleLogin(String IdToken, final Callback callback) { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { - user = task.getResult().getUser(); - userCallback(user, callback); + FirestackAuthModule.this.user = task.getResult().getUser(); + userCallback(FirestackAuthModule.this.user, callback); }else{ userErrorCallback(task, callback); } @@ -406,8 +406,8 @@ public void facebookLogin(String Token, final Callback callback) { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { - user = task.getResult().getUser(); - userCallback(user, callback); + FirestackAuthModule.this.user = task.getResult().getUser(); + userCallback(FirestackAuthModule.this.user, callback); }else{ userErrorCallback(task, callback); } @@ -421,18 +421,18 @@ public void userCallback(FirebaseUser passedUser, final Callback onComplete) { if (passedUser == null) { mAuth = FirebaseAuth.getInstance(); - final FirebaseUser user = mAuth.getCurrentUser(); + this.user = mAuth.getCurrentUser(); } else { - final FirebaseUser user = passedUser; + this.user = passedUser; } - user.getToken(true).addOnCompleteListener(new OnCompleteListener() { + this.user.getToken(true).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { WritableMap msgMap = Arguments.createMap(); WritableMap userMap = Arguments.createMap(); - if (user != null) { + if (FirestackAuthModule.this.user != null) { final String token = task.getResult().getToken(); userMap.putString("token", token); @@ -452,18 +452,18 @@ public void anonymousUserCallback(FirebaseUser passedUser, final Callback onComp if (passedUser == null) { mAuth = FirebaseAuth.getInstance(); - final FirebaseUser user = mAuth.getCurrentUser(); + this.user = mAuth.getCurrentUser(); } else { - final FirebaseUser user = passedUser; + this.user = passedUser; } - user.getToken(true).addOnCompleteListener(new OnCompleteListener() { + this.user.getToken(true).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { WritableMap msgMap = Arguments.createMap(); WritableMap userMap = Arguments.createMap(); - if (user != null) { + if (FirestackAuthModule.this.user != null) { final String token = task.getResult().getToken(); userMap.putString("token", token); From e7a8662d599dbfcf359376470949468ebc522033 Mon Sep 17 00:00:00 2001 From: Matt Jeanes Date: Fri, 28 Oct 2016 15:06:23 -0400 Subject: [PATCH 2/7] Android: fix userMap not being used in userCallback & anonymousUserCallback --- .../io/fullstack/firestack/FirestackAuth.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/android/src/main/java/io/fullstack/firestack/FirestackAuth.java b/android/src/main/java/io/fullstack/firestack/FirestackAuth.java index 77a997d..7c0c2bb 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackAuth.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackAuth.java @@ -417,7 +417,6 @@ public void onComplete(@NonNull Task task) { // Internal helpers public void userCallback(FirebaseUser passedUser, final Callback onComplete) { - WritableMap userMap = getUserMap(); if (passedUser == null) { mAuth = FirebaseAuth.getInstance(); @@ -429,14 +428,13 @@ public void userCallback(FirebaseUser passedUser, final Callback onComplete) { this.user.getToken(true).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { - WritableMap msgMap = Arguments.createMap(); - WritableMap userMap = Arguments.createMap(); - + WritableMap msgMap = Arguments.createMap(); + WritableMap userMap = getUserMap(); if (FirestackAuthModule.this.user != null) { - final String token = task.getResult().getToken(); + final String token = task.getResult().getToken(); - userMap.putString("token", token); - userMap.putBoolean("anonymous", false); + userMap.putString("token", token); + userMap.putBoolean("anonymous", false); } msgMap.putMap("user", userMap); @@ -448,7 +446,6 @@ public void onComplete(@NonNull Task task) { // TODO: Reduce to one method public void anonymousUserCallback(FirebaseUser passedUser, final Callback onComplete) { - WritableMap userMap = getUserMap(); if (passedUser == null) { mAuth = FirebaseAuth.getInstance(); @@ -460,14 +457,14 @@ public void anonymousUserCallback(FirebaseUser passedUser, final Callback onComp this.user.getToken(true).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { - WritableMap msgMap = Arguments.createMap(); - WritableMap userMap = Arguments.createMap(); + WritableMap msgMap = Arguments.createMap(); + WritableMap userMap = getUserMap(); if (FirestackAuthModule.this.user != null) { - final String token = task.getResult().getToken(); + final String token = task.getResult().getToken(); - userMap.putString("token", token); - userMap.putBoolean("anonymous", true); + userMap.putString("token", token); + userMap.putBoolean("anonymous", true); } msgMap.putMap("user", userMap); From 54a564cc4ca5bd7334360036ae3017315e337023 Mon Sep 17 00:00:00 2001 From: Matt Jeanes Date: Tue, 1 Nov 2016 10:07:24 -0400 Subject: [PATCH 3/7] Upgrade google play services and firebase to 9.8.0 --- android/build.gradle | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 4009637..a06d876 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -20,13 +20,13 @@ android { dependencies { compile 'com.facebook.react:react-native:0.20.+' - compile 'com.google.android.gms:play-services-base:9.6.1' + compile 'com.google.android.gms:play-services-base:9.8.0' - compile 'com.google.firebase:firebase-core:9.6.0' - compile 'com.google.firebase:firebase-auth:9.6.0' - compile 'com.google.firebase:firebase-analytics:9.6.0' - compile 'com.google.firebase:firebase-database:9.6.0' - compile 'com.google.firebase:firebase-storage:9.6.0' - compile 'com.google.firebase:firebase-messaging:9.6.0' + compile 'com.google.firebase:firebase-core:9.8.0' + compile 'com.google.firebase:firebase-auth:9.8.0' + compile 'com.google.firebase:firebase-analytics:9.8.0' + compile 'com.google.firebase:firebase-database:9.8.0' + compile 'com.google.firebase:firebase-storage:9.8.0' + compile 'com.google.firebase:firebase-messaging:9.8.0' } From f484cbdebf70892ec883e1811ce7c8573f01e984 Mon Sep 17 00:00:00 2001 From: Matt Jeanes Date: Tue, 1 Nov 2016 16:04:26 -0400 Subject: [PATCH 4/7] Android: Fix .on() listeners not getting removed / called immediately on setup --- .../java/io/fullstack/firestack/FirestackDatabase.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java index 537638e..8b262a0 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java @@ -468,7 +468,8 @@ public void off(final String path, final String name, final Callback callback) { ref.removeChildEventListener(); } - this.removeDBHandle(path, name); + String key = this.keyPath(path, name); + this.removeDBHandle(key); Log.d(TAG, "Removed listener " + name); WritableMap resp = Arguments.createMap(); resp.putString("handle", path); @@ -583,12 +584,11 @@ private void saveDBHandle(final String path, final String eventName, final FirestackDBReference dbRef) { String key = this.keyPath(path, eventName); - this.removeDBHandle(key, eventName); + this.removeDBHandle(key); mDBListeners.put(key, dbRef); } - private void removeDBHandle(final String path, final String eventName) { - String key = this.keyPath(path, eventName); + private void removeDBHandle(final String key) { if (mDBListeners.containsKey(key)) { FirestackDBReference r = mDBListeners.get(key); r.cleanup(); From 7c8c0b95002d404868762ab7d2815d6fcd28f6af Mon Sep 17 00:00:00 2001 From: Matt Jeanes Date: Wed, 2 Nov 2016 12:49:13 -0400 Subject: [PATCH 5/7] Fix listeners getting called when it's not their turn --- .../firestack/FirestackDatabase.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java index 8b262a0..90fdf5f 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java @@ -64,30 +64,40 @@ public void addChildEventListener(final String name, final ReadableArray modifie mEventListener = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { - self.handleDatabaseEvent(name, mPath, dataSnapshot); + if (name.equals("child_added")) { + self.handleDatabaseEvent(name, mPath, dataSnapshot); + } } @Override public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) { - self.handleDatabaseEvent(name, mPath, dataSnapshot); + if (name.equals("child_changed")) { + self.handleDatabaseEvent(name, mPath, dataSnapshot); + } } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { - self.handleDatabaseEvent(name, mPath, dataSnapshot); + if (name.equals("child_removed")) { + self.handleDatabaseEvent(name, mPath, dataSnapshot); + } } @Override public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) { - self.handleDatabaseEvent(name, mPath, dataSnapshot); + if (name.equals("child_moved")) { + self.handleDatabaseEvent(name, mPath, dataSnapshot); + } } @Override public void onCancelled(DatabaseError error) { - self.handleDatabaseError(name, mPath, error); + //if (name.equals("child_added")) { + //self.handleDatabaseError(name, mPath, error); + //} } }; - + Query ref = this.getDatabaseQueryAtPathAndModifiers(modifiers); ref.addChildEventListener(mEventListener); this.setListeningTo(mPath, name); From 28fdcd0738973a61ea5f7b01aaa0224225c31a1a Mon Sep 17 00:00:00 2001 From: Matt Jeanes Date: Thu, 3 Nov 2016 18:45:06 -0400 Subject: [PATCH 6/7] Fix Java Database Listeners Various fixes / changes: - dont call removeDBHandlers() when calling .on() - Dont destroy and recreate the monolithic listener for each path - handleDatabaseEvent only forwards it to javascript if anyone is listening to that eventType Previously: - Calling ref.on(eventType) would erase pre-existing listeners - eventType handlers were getting called with the wrong eventType --- .../firestack/FirestackDatabase.java | 86 ++++++++----------- 1 file changed, 35 insertions(+), 51 deletions(-) diff --git a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java index caa3f00..d95a284 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java @@ -62,42 +62,34 @@ public void setModifiers(final ReadableArray modifiers) { public void addChildEventListener(final String name, final ReadableArray modifiers) { final FirestackDBReference self = this; - mEventListener = new ChildEventListener() { - @Override - public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { - if (name.equals("child_added")) { - self.handleDatabaseEvent(name, mPath, dataSnapshot); + if (mEventListener == null) { + mEventListener = new ChildEventListener() { + @Override + public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { + self.handleDatabaseEvent("child_added", mPath, dataSnapshot); } - } - @Override - public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) { - if (name.equals("child_changed")) { - self.handleDatabaseEvent(name, mPath, dataSnapshot); + @Override + public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) { + self.handleDatabaseEvent("child_changed", mPath, dataSnapshot); } - } - @Override - public void onChildRemoved(DataSnapshot dataSnapshot) { - if (name.equals("child_removed")) { - self.handleDatabaseEvent(name, mPath, dataSnapshot); + @Override + public void onChildRemoved(DataSnapshot dataSnapshot) { + self.handleDatabaseEvent("child_removed", mPath, dataSnapshot); } - } - @Override - public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) { - if (name.equals("child_moved")) { - self.handleDatabaseEvent(name, mPath, dataSnapshot); + @Override + public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) { + self.handleDatabaseEvent("child_moved", mPath, dataSnapshot); } - } - @Override - public void onCancelled(DatabaseError error) { - //if (name.equals("child_added")) { - //self.handleDatabaseError(name, mPath, error); - //} - } - }; + @Override + public void onCancelled(DatabaseError error) { + self.handleDatabaseError(name, mPath, error); + } + }; + } Query ref = this.getDatabaseQueryAtPathAndModifiers(modifiers); ref.addChildEventListener(mEventListener); @@ -196,8 +188,11 @@ public void removeValueEventListener() { } private void handleDatabaseEvent(final String name, final String path, final DataSnapshot dataSnapshot) { + if (!FirestackDBReference.this.isListeningTo(path, name)) { + return; + } WritableMap data = FirestackUtils.dataSnapshotToMap(name, path, dataSnapshot); - WritableMap evt = Arguments.createMap(); + WritableMap evt = Arguments.createMap(); evt.putString("eventName", name); evt.putString("path", path); evt.putMap("body", data); @@ -470,18 +465,8 @@ public void onOnce(final String path, @ReactMethod public void off(final String path, final String name, final Callback callback) { - // TODO - FirestackDBReference ref = this.getDBHandle(path, name); - - if (name.equals("value")) { - ref.removeValueEventListener(); - } else { - ref.removeChildEventListener(); - } - - String key = this.keyPath(path, name); - this.removeDBHandle(key); - Log.d(TAG, "Removed listener " + name); + String keyPath = this.keyPath(path, name); + this.removeDBHandle(keyPath); WritableMap resp = Arguments.createMap(); resp.putString("handle", path); resp.putString("result", "success"); @@ -582,26 +567,25 @@ private void handleCallback( } private FirestackDBReference getDBHandle(final String path, final String eventName) { - String key = this.keyPath(path, eventName); - if (!mDBListeners.containsKey(key)) { + String keyPath = this.keyPath(path, eventName); + if (!mDBListeners.containsKey(keyPath)) { ReactContext ctx = getReactApplicationContext(); - mDBListeners.put(key, new FirestackDBReference(ctx, path)); + mDBListeners.put(keyPath, new FirestackDBReference(ctx, path)); } - return mDBListeners.get(key); + return mDBListeners.get(keyPath); } private void saveDBHandle(final String path, final String eventName, final FirestackDBReference dbRef) { - String key = this.keyPath(path, eventName); - this.removeDBHandle(key); - mDBListeners.put(key, dbRef); + String keyPath = this.keyPath(path, eventName); + mDBListeners.put(keyPath, dbRef); } - private void removeDBHandle(final String key) { - if (mDBListeners.containsKey(key)) { - FirestackDBReference r = mDBListeners.get(key); + private void removeDBHandle(final String keyPath) { + if (mDBListeners.containsKey(keyPath)) { + FirestackDBReference r = mDBListeners.get(keyPath); r.cleanup(); } } From eeeacc99c7600951974ce15fefe24b1c2a105766 Mon Sep 17 00:00:00 2001 From: Matt Jeanes Date: Fri, 4 Nov 2016 13:59:37 -0400 Subject: [PATCH 7/7] Cleanup listeners and add a little bit of documentation --- .../firestack/FirestackDatabase.java | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java index d95a284..61cda5d 100644 --- a/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java +++ b/android/src/main/java/io/fullstack/firestack/FirestackDatabase.java @@ -3,16 +3,11 @@ import android.content.Context; import android.util.Log; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.ListIterator; -import java.util.ArrayList; import java.util.Map; import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -24,11 +19,6 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReactContext; -import com.google.android.gms.tasks.OnCompleteListener; -import com.google.android.gms.tasks.OnFailureListener; -import com.google.android.gms.tasks.Task; -import com.google.firebase.FirebaseApp; - import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.ChildEventListener; @@ -146,6 +136,9 @@ public Boolean isListeningTo(final String path, final String evtName) { return mListeners.containsKey(key); } + /** + * Note: these path/eventType listeners only get removed when javascript calls .off() and cleanup is run on the entire path + */ public void setListeningTo(final String path, final String evtName) { String key = this.pathListeningKey(path, evtName); mListeners.put(key, true); @@ -179,12 +172,16 @@ public void removeChildEventListener() { } public void removeValueEventListener() { + DatabaseReference ref = this.getDatabaseRef(); if (mValueListener != null) { - DatabaseReference ref = this.getDatabaseRef(); ref.removeEventListener(mValueListener); this.notListeningTo(mPath, "value"); mValueListener = null; } + if (mOnceValueListener != null) { + ref.removeEventListener(mOnceValueListener); + mOnceValueListener = null; + } } private void handleDatabaseEvent(final String name, final String path, final DataSnapshot dataSnapshot) { @@ -435,7 +432,7 @@ public void on(final String path, final ReadableArray modifiers, final String name, final Callback callback) { - FirestackDBReference ref = this.getDBHandle(path, name); + FirestackDBReference ref = this.getDBHandle(path); WritableMap resp = Arguments.createMap(); @@ -445,7 +442,7 @@ public void on(final String path, ref.addChildEventListener(name, modifiers); } - this.saveDBHandle(path, name, ref); + this.saveDBHandle(path, ref); resp.putString("result", "success"); Log.d(TAG, "Added listener " + name + " for " + ref); @@ -459,14 +456,20 @@ public void onOnce(final String path, final String name, final Callback callback) { Log.d(TAG, "Setting one-time listener on event: " + name + " for path " + path); - FirestackDBReference ref = this.getDBHandle(path, "once"); + FirestackDBReference ref = this.getDBHandle(path); ref.addOnceValueEventListener(modifiers, callback); } + /** + * At the time of this writing, off() only gets called when there are no more subscribers to a given path. + * `mListeners` might therefore be out of sync (though javascript isnt listening for those eventTypes, so + * it doesn't really matter- just polluting the RN bridge a little more than necessary. + * off() should therefore clean *everything* up + */ @ReactMethod - public void off(final String path, final String name, final Callback callback) { - String keyPath = this.keyPath(path, name); - this.removeDBHandle(keyPath); + public void off(final String path, @Deprecated final String name, final Callback callback) { + this.removeDBHandle(path); + Log.d(TAG, "Removed listener " + path); WritableMap resp = Arguments.createMap(); resp.putString("handle", path); resp.putString("result", "success"); @@ -566,27 +569,24 @@ private void handleCallback( } } - private FirestackDBReference getDBHandle(final String path, final String eventName) { - String keyPath = this.keyPath(path, eventName); - if (!mDBListeners.containsKey(keyPath)) { + private FirestackDBReference getDBHandle(final String path) { + if (!mDBListeners.containsKey(path)) { ReactContext ctx = getReactApplicationContext(); - mDBListeners.put(keyPath, new FirestackDBReference(ctx, path)); + mDBListeners.put(path, new FirestackDBReference(ctx, path)); } - return mDBListeners.get(keyPath); + return mDBListeners.get(path); } - private void saveDBHandle(final String path, - final String eventName, - final FirestackDBReference dbRef) { - String keyPath = this.keyPath(path, eventName); - mDBListeners.put(keyPath, dbRef); + private void saveDBHandle(final String path, final FirestackDBReference dbRef) { + mDBListeners.put(path, dbRef); } - private void removeDBHandle(final String keyPath) { - if (mDBListeners.containsKey(keyPath)) { - FirestackDBReference r = mDBListeners.get(keyPath); + private void removeDBHandle(final String path) { + if (mDBListeners.containsKey(path)) { + FirestackDBReference r = mDBListeners.get(path); r.cleanup(); + mDBListeners.remove(path); } }