Skip to content

Commit d8dbf87

Browse files
committed
Unify change event listeners
Change-Id: Ie40689d23e77b8885d369856b86479252382946a
1 parent f9d8aba commit d8dbf87

File tree

14 files changed

+167
-172
lines changed

14 files changed

+167
-172
lines changed

app/src/main/java/com/firebase/uidemo/firestore/FirestoreChatActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import butterknife.OnClick;
3131

3232
/**
33-
* TODO
33+
* Class demonstrating a simple real-time chat app that relies on {@link FirestoreRecyclerAdapter}.
3434
*/
3535
public class FirestoreChatActivity extends AppCompatActivity implements FirebaseAuth.AuthStateListener {
3636

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.firebase.ui.common;
2+
3+
/**
4+
* TODO(samstern): Document
5+
*/
6+
public interface BaseChangeEventListener<S, E> {
7+
8+
/**
9+
* A callback for when a child event occurs.
10+
*
11+
* @param type The type of the event.
12+
* @param snapshot The snapshot of the changed child.
13+
* @param newIndex The new index of the element, or -1 of it is no longer present
14+
* @param oldIndex The previous index of the element, or -1 if it was not
15+
* previously tracked.
16+
*/
17+
void onChildChanged(ChangeEventType type, S snapshot,
18+
int newIndex, int oldIndex);
19+
20+
/**
21+
* Callback triggered after all child events in a particular snapshot have been
22+
* processed.
23+
* <p>
24+
* Useful for batch events, such as removing a loading indicator after initial load
25+
* or a large update batch.
26+
*/
27+
void onDataChanged();
28+
29+
/**
30+
* Callback when an error has been detected in the underlying listener.
31+
* @param e the error that occurred.
32+
*/
33+
void onError(E e);
34+
35+
}

common/src/main/java/com/firebase/ui/common/BaseObservableSnapshotArray.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
*/
1818
public abstract class BaseObservableSnapshotArray<S, L, E> extends AbstractList<S> {
1919

20-
protected final List<L> mListeners = new CopyOnWriteArrayList<>();
21-
protected BaseSnapshotParser<S, E> mParser;
20+
private final List<L> mListeners = new CopyOnWriteArrayList<>();
21+
private BaseSnapshotParser<S, E> mParser;
2222

2323
private boolean mHasDataChanged = false;
2424

@@ -44,6 +44,13 @@ public BaseObservableSnapshotArray(@NonNull BaseSnapshotParser<S, E> parser) {
4444
@CallSuper
4545
protected void onCreate() {}
4646

47+
/**
48+
* Called when a new listener has been added to the array. This is a good time to pass initial
49+
* state and fire backlogged events
50+
* @param listener the added listener.
51+
*/
52+
protected void onListenerAdded(L listener) {};
53+
4754
/**
4855
* Called when the {@link BaseObservableSnapshotArray} is inactive and should stop listening to the
4956
* Firebase database.
@@ -61,7 +68,14 @@ protected void onDestroy() {
6168
@CallSuper
6269
public L addChangeEventListener(@NonNull L listener) {
6370
Preconditions.checkNotNull(listener);
71+
boolean wasListening = isListening();
72+
6473
mListeners.add(listener);
74+
onListenerAdded(listener);
75+
76+
if (!wasListening) {
77+
onCreate();
78+
}
6579

6680
return listener;
6781
}
@@ -90,6 +104,13 @@ public void removeAllListeners() {
90104
}
91105
}
92106

107+
/**
108+
* Get all active listeners.
109+
*/
110+
public List<L> getListeners() {
111+
return mListeners;
112+
}
113+
93114
/**
94115
* @return true if the array is listening for change events from the Firebase
95116
* database, false otherwise
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.firebase.ui.common;
2+
3+
/**
4+
* Enumeration of change event types for children of an observable snapshot array.
5+
*/
6+
public enum ChangeEventType {
7+
8+
/**
9+
* An element was added to the array.
10+
*/
11+
ADDED,
12+
13+
/**
14+
* An element was removed from the array.
15+
*/
16+
REMOVED,
17+
18+
/**
19+
* An element in the array has new content.
20+
*/
21+
CHANGED,
22+
23+
/**
24+
* An element in the array has new content, which caused a change in position.
25+
*/
26+
MOVED
27+
28+
}

database/src/androidTest/java/com/firebase/ui/database/TestUtils.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.content.Context;
44

5+
import com.firebase.ui.common.ChangeEventType;
56
import com.google.firebase.FirebaseApp;
67
import com.google.firebase.FirebaseOptions;
78
import com.google.firebase.database.DataSnapshot;
@@ -40,7 +41,7 @@ public static ChangeEventListener runAndWaitUntil(ObservableSnapshotArray array,
4041
final Semaphore semaphore = new Semaphore(0);
4142
ChangeEventListener listener = array.addChangeEventListener(new ChangeEventListener() {
4243
@Override
43-
public void onChildChanged(ChangeEventListener.EventType type,
44+
public void onChildChanged(ChangeEventType type,
4445
DataSnapshot snapshot,
4546
int index,
4647
int oldIndex) {
@@ -52,7 +53,7 @@ public void onDataChanged() {
5253
}
5354

5455
@Override
55-
public void onCancelled(DatabaseError error) {
56+
public void onError(DatabaseError error) {
5657
throw new IllegalStateException(error.toException());
5758
}
5859
});
Lines changed: 5 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,10 @@
11
package com.firebase.ui.database;
22

3-
import com.google.firebase.database.ChildEventListener;
3+
import com.firebase.ui.common.BaseChangeEventListener;
44
import com.google.firebase.database.DataSnapshot;
55
import com.google.firebase.database.DatabaseError;
66

7-
public interface ChangeEventListener {
8-
9-
/**
10-
* The type of event received when a child has been updated.
11-
*/
12-
enum EventType {
13-
/**
14-
* An onChildAdded event was received.
15-
*
16-
* @see ChildEventListener#onChildAdded(DataSnapshot, String)
17-
*/
18-
ADDED,
19-
/**
20-
* An onChildChanged event was received.
21-
*
22-
* @see ChildEventListener#onChildChanged(DataSnapshot, String)
23-
*/
24-
CHANGED,
25-
/**
26-
* An onChildRemoved event was received.
27-
*
28-
* @see ChildEventListener#onChildRemoved(DataSnapshot)
29-
*/
30-
REMOVED,
31-
/**
32-
* An onChildMoved event was received.
33-
*
34-
* @see ChildEventListener#onChildMoved(DataSnapshot, String)
35-
*/
36-
MOVED
37-
}
38-
39-
/**
40-
* A callback for when a child has changed in FirebaseArray.
41-
*
42-
* @param type The type of event received
43-
* @param snapshot the {@link DataSnapshot} of the changed child.
44-
* @param index The index at which the change occurred
45-
* @param oldIndex If {@code type} is a moved event, the previous index of the moved child. For
46-
* any other event, {@code oldIndex} will be -1.
47-
*/
48-
void onChildChanged(EventType type, DataSnapshot snapshot, int index, int oldIndex);
49-
50-
/**
51-
* This method will be triggered each time updates from the database have been completely
52-
* processed. So the first time this method is called, the initial data has been loaded -
53-
* including the case when no data at all is available. Each next time the method is called, a
54-
* complete update (potentially consisting of updates to multiple child items) has been
55-
* completed.
56-
* <p>
57-
* You would typically override this method to hide a loading indicator (after the initial load)
58-
* or to complete a batch update to a UI element.
59-
*/
60-
void onDataChanged();
61-
62-
/**
63-
* This method will be triggered in the event that this listener either failed at the server, or
64-
* is removed as a result of the security and Firebase Database rules.
65-
*
66-
* @param error A description of the error that occurred
67-
*/
68-
void onCancelled(DatabaseError error);
69-
}
7+
/**
8+
* Listener for changes to {@link FirebaseArray}.
9+
*/
10+
public interface ChangeEventListener extends BaseChangeEventListener<DataSnapshot, DatabaseError> {}

database/src/main/java/com/firebase/ui/database/FirebaseArray.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.firebase.ui.database;
1616

17+
import com.firebase.ui.common.ChangeEventType;
1718
import com.google.firebase.database.ChildEventListener;
1819
import com.google.firebase.database.DataSnapshot;
1920
import com.google.firebase.database.DatabaseError;
@@ -87,23 +88,23 @@ public void onChildAdded(DataSnapshot snapshot, String previousChildKey) {
8788

8889
mSnapshots.add(index, snapshot);
8990

90-
notifyChangeEventListeners(ChangeEventListener.EventType.ADDED, snapshot, index);
91+
notifyChangeEventListeners(ChangeEventType.ADDED, snapshot, index);
9192
}
9293

9394
@Override
9495
public void onChildChanged(DataSnapshot snapshot, String previousChildKey) {
9596
int index = getIndexForKey(snapshot.getKey());
9697

9798
updateData(index, snapshot);
98-
notifyChangeEventListeners(ChangeEventListener.EventType.CHANGED, snapshot, index);
99+
notifyChangeEventListeners(ChangeEventType.CHANGED, snapshot, index);
99100
}
100101

101102
@Override
102103
public void onChildRemoved(DataSnapshot snapshot) {
103104
int index = getIndexForKey(snapshot.getKey());
104105

105106
removeData(index);
106-
notifyChangeEventListeners(ChangeEventListener.EventType.REMOVED, snapshot, index);
107+
notifyChangeEventListeners(ChangeEventType.REMOVED, snapshot, index);
107108
}
108109

109110
@Override
@@ -114,7 +115,7 @@ public void onChildMoved(DataSnapshot snapshot, String previousChildKey) {
114115
int newIndex = previousChildKey == null ? 0 : (getIndexForKey(previousChildKey) + 1);
115116
mSnapshots.add(newIndex, snapshot);
116117

117-
notifyChangeEventListeners(ChangeEventListener.EventType.MOVED,
118+
notifyChangeEventListeners(ChangeEventType.MOVED,
118119
snapshot,
119120
newIndex,
120121
oldIndex);

database/src/main/java/com/firebase/ui/database/FirebaseIndexArray.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import android.support.v7.widget.RecyclerView;
1818
import android.util.Log;
1919

20+
import com.firebase.ui.common.ChangeEventType;
2021
import com.google.firebase.database.DataSnapshot;
2122
import com.google.firebase.database.DatabaseError;
2223
import com.google.firebase.database.DatabaseReference;
@@ -104,7 +105,7 @@ protected void onDestroy() {
104105
}
105106

106107
@Override
107-
public void onChildChanged(EventType type, DataSnapshot snapshot, int index, int oldIndex) {
108+
public void onChildChanged(ChangeEventType type, DataSnapshot snapshot, int index, int oldIndex) {
108109
switch (type) {
109110
case ADDED:
110111
onKeyAdded(snapshot);
@@ -131,7 +132,7 @@ public void onDataChanged() {
131132
}
132133

133134
@Override
134-
public void onCancelled(DatabaseError error) {
135+
public void onError(DatabaseError error) {
135136
Log.e(TAG, "A fatal error occurred retrieving the necessary keys to populate your adapter.");
136137
}
137138

@@ -177,7 +178,7 @@ protected void onKeyMoved(DataSnapshot data, int index, int oldIndex) {
177178
DataSnapshot snapshot = removeData(oldIndex);
178179
mHasPendingMoveOrDelete = true;
179180
mDataSnapshots.add(index, snapshot);
180-
notifyChangeEventListeners(EventType.MOVED, snapshot, index, oldIndex);
181+
notifyChangeEventListeners(ChangeEventType.MOVED, snapshot, index, oldIndex);
181182
}
182183
}
183184

@@ -189,7 +190,7 @@ protected void onKeyRemoved(DataSnapshot data, int index) {
189190
if (isKeyAtIndex(key, index)) {
190191
DataSnapshot snapshot = removeData(index);
191192
mHasPendingMoveOrDelete = true;
192-
notifyChangeEventListeners(EventType.REMOVED, snapshot, index);
193+
notifyChangeEventListeners(ChangeEventType.REMOVED, snapshot, index);
193194
}
194195
}
195196

@@ -234,12 +235,12 @@ public void onDataChange(DataSnapshot snapshot) {
234235
if (isKeyAtIndex(key, index)) {
235236
// We already know about this data, just update it
236237
updateData(index, snapshot);
237-
notifyChangeEventListeners(EventType.CHANGED, snapshot, index);
238+
notifyChangeEventListeners(ChangeEventType.CHANGED, snapshot, index);
238239
notifyListenersOnDataChanged();
239240
} else {
240241
// We don't already know about this data, add it
241242
mDataSnapshots.add(index, snapshot);
242-
notifyChangeEventListeners(EventType.ADDED, snapshot, index);
243+
notifyChangeEventListeners(ChangeEventType.ADDED, snapshot, index);
243244

244245
mKeysWithPendingData.remove(key);
245246
if (mKeysWithPendingData.isEmpty()) notifyListenersOnDataChanged();
@@ -248,7 +249,7 @@ public void onDataChange(DataSnapshot snapshot) {
248249
if (isKeyAtIndex(key, index)) {
249250
// This data has disappeared, remove it
250251
removeData(index);
251-
notifyChangeEventListeners(EventType.REMOVED, snapshot, index);
252+
notifyChangeEventListeners(ChangeEventType.REMOVED, snapshot, index);
252253
notifyListenersOnDataChanged();
253254
} else {
254255
// Data does not exist

database/src/main/java/com/firebase/ui/database/FirebaseListAdapter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import android.widget.BaseAdapter;
1515
import android.widget.ListView;
1616

17+
import com.firebase.ui.common.ChangeEventType;
1718
import com.google.firebase.database.DataSnapshot;
1819
import com.google.firebase.database.DatabaseError;
1920
import com.google.firebase.database.DatabaseReference;
@@ -140,7 +141,7 @@ void cleanup(LifecycleOwner source, Lifecycle.Event event) {
140141
}
141142

142143
@Override
143-
public void onChildChanged(ChangeEventListener.EventType type,
144+
public void onChildChanged(ChangeEventType type,
144145
DataSnapshot snapshot,
145146
int index,
146147
int oldIndex) {
@@ -152,7 +153,7 @@ public void onDataChanged() {
152153
}
153154

154155
@Override
155-
public void onCancelled(DatabaseError error) {
156+
public void onError(DatabaseError error) {
156157
Log.w(TAG, error.toException());
157158
}
158159

database/src/main/java/com/firebase/ui/database/FirebaseRecyclerAdapter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import android.view.View;
1212
import android.view.ViewGroup;
1313

14+
import com.firebase.ui.common.ChangeEventType;
1415
import com.google.firebase.database.DataSnapshot;
1516
import com.google.firebase.database.DatabaseError;
1617
import com.google.firebase.database.DatabaseReference;
@@ -144,7 +145,7 @@ void cleanup(LifecycleOwner source, Lifecycle.Event event) {
144145
}
145146

146147
@Override
147-
public void onChildChanged(ChangeEventListener.EventType type,
148+
public void onChildChanged(ChangeEventType type,
148149
DataSnapshot snapshot,
149150
int index,
150151
int oldIndex) {
@@ -171,7 +172,7 @@ public void onDataChanged() {
171172
}
172173

173174
@Override
174-
public void onCancelled(DatabaseError error) {
175+
public void onError(DatabaseError error) {
175176
Log.w(TAG, error.toException());
176177
}
177178

0 commit comments

Comments
 (0)