Skip to content

Commit 585d188

Browse files
committed
Fixed android database bug
1 parent f1bea9a commit 585d188

File tree

4 files changed

+144
-91
lines changed

4 files changed

+144
-91
lines changed

android/src/main/java/io/fullstack/firestack/FirestackDatabase.java

Lines changed: 71 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class FirestackDBReference {
4242

4343
private String mPath;
4444
private ReadableArray mModifiers;
45-
private Map mListeners;
45+
private HashMap<String, Boolean> mListeners = new HashMap<String, Boolean>();
4646
private FirestackDatabaseModule mDatabase;
4747
private ChildEventListener mEventListener;
4848
private ValueEventListener mValueListener;
@@ -64,31 +64,33 @@ public void addChildEventListener(final String name, final ReadableArray modifie
6464
mEventListener = new ChildEventListener() {
6565
@Override
6666
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
67-
self.handleDatabaseEvent(name, dataSnapshot);
67+
self.handleDatabaseEvent(name, mPath, dataSnapshot);
6868
}
6969

7070
@Override
7171
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
72-
self.handleDatabaseEvent(name, dataSnapshot);
72+
self.handleDatabaseEvent(name, mPath, dataSnapshot);
7373
}
7474

7575
@Override
7676
public void onChildRemoved(DataSnapshot dataSnapshot) {
77-
self.handleDatabaseEvent(name, dataSnapshot);
77+
self.handleDatabaseEvent(name, mPath, dataSnapshot);
7878
}
7979

8080
@Override
8181
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
82-
self.handleDatabaseEvent(name, dataSnapshot);
82+
self.handleDatabaseEvent(name, mPath, dataSnapshot);
8383
}
8484

8585
@Override
8686
public void onCancelled(DatabaseError error) {
87-
self.handleDatabaseError(name, error);
87+
self.handleDatabaseError(name, mPath, error);
8888
}
8989
};
90+
9091
Query ref = this.getDatabaseQueryAtPathAndModifiers(modifiers);
9192
ref.addChildEventListener(mEventListener);
93+
this.setListeningTo(mPath, name);
9294
}
9395

9496
public void addValueEventListener(final String name, final ReadableArray modifiers) {
@@ -97,19 +99,18 @@ public void addValueEventListener(final String name, final ReadableArray modifie
9799
mValueListener = new ValueEventListener() {
98100
@Override
99101
public void onDataChange(DataSnapshot dataSnapshot) {
100-
Log.d(TAG, "onDataChange called for " + name);
101-
self.handleDatabaseEvent("value", dataSnapshot);
102+
self.handleDatabaseEvent("value", mPath, dataSnapshot);
102103
}
103104

104105
@Override
105106
public void onCancelled(DatabaseError error) {
106-
Log.d(TAG, "onDataChange onCancelled called");
107-
self.handleDatabaseError("value", error);
107+
self.handleDatabaseError("value", mPath, error);
108108
}
109109
};
110110

111111
Query ref = this.getDatabaseQueryAtPathAndModifiers(modifiers);
112112
ref.addValueEventListener(mValueListener);
113+
this.setListeningTo(mPath, "value");
113114
}
114115

115116
public void addOnceValueEventListener(final ReadableArray modifiers,
@@ -119,7 +120,7 @@ public void addOnceValueEventListener(final ReadableArray modifiers,
119120
mOnceValueListener = new ValueEventListener() {
120121
@Override
121122
public void onDataChange(DataSnapshot dataSnapshot) {
122-
WritableMap data = FirestackUtils.dataSnapshotToMap("value", dataSnapshot);
123+
WritableMap data = FirestackUtils.dataSnapshotToMap("value", mPath, dataSnapshot);
123124
callback.invoke(null, data);
124125
}
125126

@@ -137,7 +138,27 @@ public void onCancelled(DatabaseError error) {
137138
ref.addListenerForSingleValueEvent(mOnceValueListener);
138139
}
139140

141+
public Boolean isListeningTo(final String path, final String evtName) {
142+
String key = this.pathListeningKey(path, evtName);
143+
return mListeners.containsKey(key);
144+
}
145+
146+
public void setListeningTo(final String path, final String evtName) {
147+
String key = this.pathListeningKey(path, evtName);
148+
mListeners.put(key, true);
149+
}
150+
151+
public void notListeningTo(final String path, final String evtName) {
152+
String key = this.pathListeningKey(path, evtName);
153+
mListeners.remove(key);
154+
}
155+
156+
private String pathListeningKey(final String path, final String eventName) {
157+
return "listener/" + path + "/" + eventName;
158+
}
159+
140160
public void cleanup() {
161+
Log.d(TAG, "cleaning up database reference " + this);
141162
this.removeChildEventListener();
142163
this.removeValueEventListener();
143164
}
@@ -146,6 +167,10 @@ public void removeChildEventListener() {
146167
if (mEventListener != null) {
147168
DatabaseReference ref = this.getDatabaseRef();
148169
ref.removeEventListener(mEventListener);
170+
this.notListeningTo(mPath, "child_added");
171+
this.notListeningTo(mPath, "child_changed");
172+
this.notListeningTo(mPath, "child_removed");
173+
this.notListeningTo(mPath, "child_moved");
149174
mEventListener = null;
150175
}
151176
}
@@ -154,29 +179,30 @@ public void removeValueEventListener() {
154179
if (mValueListener != null) {
155180
DatabaseReference ref = this.getDatabaseRef();
156181
ref.removeEventListener(mValueListener);
182+
this.notListeningTo(mPath, "value");
157183
mValueListener = null;
158184
}
159185
}
160186

161-
private void handleDatabaseEvent(final String name, final DataSnapshot dataSnapshot) {
162-
Log.d(TAG, "handleDatabaseEvent called: " + name);
163-
WritableMap data = FirestackUtils.dataSnapshotToMap(name, dataSnapshot);
187+
private void handleDatabaseEvent(final String name, final String path, final DataSnapshot dataSnapshot) {
188+
WritableMap data = FirestackUtils.dataSnapshotToMap(name, path, dataSnapshot);
164189
WritableMap evt = Arguments.createMap();
165190
evt.putString("eventName", name);
191+
evt.putString("path", path);
166192
evt.putMap("body", data);
167193

168194
FirestackUtils.sendEvent(mReactContext, "database_event", evt);
169195
}
170196

171-
private void handleDatabaseError(final String name, final DatabaseError error) {
172-
Log.d(TAG, "handleDatabaseError called: " + name);
197+
private void handleDatabaseError(final String name, final String path, final DatabaseError error) {
173198
WritableMap err = Arguments.createMap();
174199
err.putInt("errorCode", error.getCode());
175200
err.putString("errorDetails", error.getDetails());
176201
err.putString("description", error.getMessage());
177202

178203
WritableMap evt = Arguments.createMap();
179204
evt.putString("eventName", name);
205+
evt.putString("path", path);
180206
evt.putMap("body", err);
181207

182208
FirestackUtils.sendEvent(mReactContext, "database_error", evt);
@@ -196,7 +222,6 @@ private Query getDatabaseQueryAtPathAndModifiers(final ReadableArray modifiers)
196222
while(it.hasNext()) {
197223
String str = (String) it.next();
198224

199-
Log.d(TAG, "getReference with modifiers: " + str);
200225
String[] strArr = str.split(":");
201226
String methStr = strArr[0];
202227

@@ -404,21 +429,21 @@ public void on(final String path,
404429
final ReadableArray modifiers,
405430
final String name,
406431
final Callback callback) {
407-
Log.d(TAG, "Setting a listener on event: " + name + " for path " + path);
408-
FirestackDBReference ref = this.getDBHandle(path);
432+
FirestackDBReference ref = this.getDBHandle(path, name);
433+
434+
WritableMap resp = Arguments.createMap();
409435

410436
if (name.equals("value")) {
411437
ref.addValueEventListener(name, modifiers);
412438
} else {
413439
ref.addChildEventListener(name, modifiers);
414440
}
415441

416-
this.saveDBHandle(path, ref);
417-
418-
Log.d(TAG, "Added listener " + name);
419-
WritableMap resp = Arguments.createMap();
420-
resp.putString("handle", path);
442+
this.saveDBHandle(path, name, ref);
421443
resp.putString("result", "success");
444+
Log.d(TAG, "Added listener " + name + " for " + ref);
445+
446+
resp.putString("handle", path);
422447
callback.invoke(null, resp);
423448
}
424449

@@ -428,22 +453,22 @@ public void onOnce(final String path,
428453
final String name,
429454
final Callback callback) {
430455
Log.d(TAG, "Setting one-time listener on event: " + name + " for path " + path);
431-
FirestackDBReference ref = this.getDBHandle(path);
456+
FirestackDBReference ref = this.getDBHandle(path, "once");
432457
ref.addOnceValueEventListener(modifiers, callback);
433458
}
434459

435460
@ReactMethod
436461
public void off(final String path, final String name, final Callback callback) {
437462
// TODO
438-
FirestackDBReference ref = this.getDBHandle(path);
463+
FirestackDBReference ref = this.getDBHandle(path, name);
439464

440465
if (name.equals("value")) {
441466
ref.removeValueEventListener();
442467
} else {
443468
ref.removeChildEventListener();
444469
}
445470

446-
this.removeDBHandle(path);
471+
this.removeDBHandle(path, name);
447472
Log.d(TAG, "Removed listener " + name);
448473
WritableMap resp = Arguments.createMap();
449474
resp.putString("handle", path);
@@ -544,28 +569,36 @@ private void handleCallback(
544569
}
545570
}
546571

547-
private FirestackDBReference getDBHandle(final String path) {
548-
if (!mDBListeners.containsKey(path)) {
572+
private FirestackDBReference getDBHandle(final String path, final String eventName) {
573+
String key = this.keyPath(path, eventName);
574+
if (!mDBListeners.containsKey(key)) {
549575
ReactContext ctx = getReactApplicationContext();
550-
mDBListeners.put(path, new FirestackDBReference(ctx, path));
576+
mDBListeners.put(key, new FirestackDBReference(ctx, path));
551577
}
552578

553-
return mDBListeners.get(path);
579+
return mDBListeners.get(key);
554580
}
555581

556582
private void saveDBHandle(final String path,
583+
final String eventName,
557584
final FirestackDBReference dbRef) {
558-
this.removeDBHandle(path);
559-
mDBListeners.put(path, dbRef);
585+
String key = this.keyPath(path, eventName);
586+
this.removeDBHandle(key, eventName);
587+
mDBListeners.put(key, dbRef);
560588
}
561589

562-
private void removeDBHandle(final String path) {
563-
if (mDBListeners.containsKey(path)) {
564-
FirestackDBReference r = mDBListeners.get(path);
590+
private void removeDBHandle(final String path, final String eventName) {
591+
String key = this.keyPath(path, eventName);
592+
if (mDBListeners.containsKey(key)) {
593+
FirestackDBReference r = mDBListeners.get(key);
565594
r.cleanup();
566595
}
567596
}
568597

598+
private String keyPath(final String path, final String eventName) {
599+
return path + "-" + eventName;
600+
}
601+
569602
// TODO: move to FirestackDBReference?
570603
private DatabaseReference getDatabaseReferenceAtPath(final String path) {
571604
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference(path);
@@ -583,8 +616,6 @@ private Query getDatabaseQueryAtPathAndModifiers(
583616

584617
while(it.hasNext()) {
585618
String str = (String) it.next();
586-
587-
Log.d(TAG, "getReference with modifiers: " + str);
588619
String[] strArr = str.split(":");
589620
String methStr = strArr[0];
590621

@@ -638,8 +669,8 @@ private Query getDatabaseQueryAtPathAndModifiers(
638669
return query;
639670
}
640671

641-
private WritableMap dataSnapshotToMap(String name, DataSnapshot dataSnapshot) {
642-
return FirestackUtils.dataSnapshotToMap(name, dataSnapshot);
672+
private WritableMap dataSnapshotToMap(String name, String path, DataSnapshot dataSnapshot) {
673+
return FirestackUtils.dataSnapshotToMap(name, path, dataSnapshot);
643674
}
644675

645676
private <Any> Any castSnapshotValue(DataSnapshot snapshot) {

android/src/main/java/io/fullstack/firestack/FirestackUtils.java

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ public static void sendEvent(final ReactContext context,
3939
final String eventName,
4040
final WritableMap params) {
4141
if (context.hasActiveCatalystInstance()) {
42-
Log.d(TAG, "Sending event " + eventName);
4342
context
4443
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
4544
.emit(eventName, params);
@@ -49,48 +48,51 @@ public static void sendEvent(final ReactContext context,
4948
}
5049

5150
// snapshot
52-
public static WritableMap dataSnapshotToMap(String name, DataSnapshot dataSnapshot) {
53-
WritableMap data = Arguments.createMap();
54-
55-
data.putString("key", dataSnapshot.getKey());
56-
data.putBoolean("exists", dataSnapshot.exists());
57-
data.putBoolean("hasChildren", dataSnapshot.hasChildren());
58-
59-
data.putDouble("childrenCount", dataSnapshot.getChildrenCount());
60-
if (!dataSnapshot.hasChildren() && dataSnapshot.getValue() != null) {
61-
String type = dataSnapshot.getValue().getClass().getName();
62-
switch (type) {
63-
case "java.lang.Boolean":
64-
data.putBoolean("value", (Boolean) dataSnapshot.getValue());
65-
break;
66-
case "java.lang.Long":
67-
data.putInt("value",(Integer)(((Long) dataSnapshot.getValue()).intValue()));
68-
break;
69-
case "java.lang.Double":
70-
data.putDouble("value",(Double) dataSnapshot.getValue());
71-
break;
72-
case "java.lang.String":
73-
data.putString("value",(String) dataSnapshot.getValue());
74-
break;
75-
default:
76-
data.putString("value", null);
51+
public static WritableMap dataSnapshotToMap(String name,
52+
String path,
53+
DataSnapshot dataSnapshot) {
54+
WritableMap data = Arguments.createMap();
55+
56+
data.putString("path", path);
57+
data.putString("key", dataSnapshot.getKey());
58+
data.putBoolean("exists", dataSnapshot.exists());
59+
data.putBoolean("hasChildren", dataSnapshot.hasChildren());
60+
61+
data.putDouble("childrenCount", dataSnapshot.getChildrenCount());
62+
if (!dataSnapshot.hasChildren() && dataSnapshot.getValue() != null) {
63+
String type = dataSnapshot.getValue().getClass().getName();
64+
switch (type) {
65+
case "java.lang.Boolean":
66+
data.putBoolean("value", (Boolean) dataSnapshot.getValue());
67+
break;
68+
case "java.lang.Long":
69+
data.putInt("value",(Integer)(((Long) dataSnapshot.getValue()).intValue()));
70+
break;
71+
case "java.lang.Double":
72+
data.putDouble("value",(Double) dataSnapshot.getValue());
73+
break;
74+
case "java.lang.String":
75+
data.putString("value",(String) dataSnapshot.getValue());
76+
break;
77+
default:
78+
data.putString("value", null);
79+
}
80+
}else{
81+
WritableMap valueMap = FirestackUtils.castSnapshotValue(dataSnapshot);
82+
data.putMap("value", valueMap);
7783
}
78-
}else{
79-
WritableMap valueMap = FirestackUtils.castSnapshotValue(dataSnapshot);
80-
data.putMap("value", valueMap);
81-
}
8284

83-
Object priority = dataSnapshot.getPriority();
84-
if (priority == null) {
85-
data.putString("priority", null);
86-
} else {
87-
data.putString("priority", priority.toString());
88-
}
85+
Object priority = dataSnapshot.getPriority();
86+
if (priority == null) {
87+
data.putString("priority", null);
88+
} else {
89+
data.putString("priority", priority.toString());
90+
}
8991

90-
WritableMap eventMap = Arguments.createMap();
91-
eventMap.putString("eventName", name);
92-
eventMap.putMap("snapshot", data);
93-
return eventMap;
92+
WritableMap eventMap = Arguments.createMap();
93+
eventMap.putString("eventName", name);
94+
eventMap.putMap("snapshot", data);
95+
return eventMap;
9496
}
9597

9698
public static <Any> Any castSnapshotValue(DataSnapshot snapshot) {

0 commit comments

Comments
 (0)