Skip to content

Commit 5ddf442

Browse files
committed
Some more fiddling
Change-Id: Ie28d94d6ffa7bdbadd8e72a064538a3bf28dfc05
1 parent 4ac2819 commit 5ddf442

File tree

14 files changed

+154
-86
lines changed

14 files changed

+154
-86
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.firebase.ui.common;
2+
3+
import android.support.annotation.RestrictTo;
4+
5+
import java.util.HashMap;
6+
import java.util.Map;
7+
8+
/**
9+
* Implementation of {@link BaseSnapshotParser} that caches results,
10+
* so parsing a snapshot repeatedly is not expensive.
11+
*/
12+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
13+
public abstract class BaseCachingSnapshotParser<S, T> implements BaseSnapshotParser<S, T> {
14+
15+
private Map<String, T> mObjectCache = new HashMap<>();
16+
private BaseSnapshotParser<S, T> mInnerParser;
17+
18+
// TODO(samstern): Can probably use this in RTDB module as well, CachingOSA is not necessary.
19+
public BaseCachingSnapshotParser(BaseSnapshotParser<S, T> innerParser) {
20+
mInnerParser = innerParser;
21+
}
22+
23+
/**
24+
* Get a unique identifier for a snapshot, should not depend on snapshot content.
25+
*/
26+
public abstract String getId(S snapshot);
27+
28+
@Override
29+
public T parseSnapshot(S snapshot) {
30+
String id = getId(snapshot);
31+
if (mObjectCache.containsKey(id)) {
32+
return mObjectCache.get(id);
33+
} else {
34+
T object = mInnerParser.parseSnapshot(snapshot);
35+
mObjectCache.put(id, object);
36+
return object;
37+
}
38+
}
39+
40+
/**
41+
* Clear all data in the cache.
42+
*/
43+
public void clearData() {
44+
mObjectCache.clear();
45+
}
46+
47+
/**
48+
* Invalidate the cache for a certain document ID.
49+
*/
50+
public void invalidate(String id) {
51+
mObjectCache.remove(id);
52+
}
53+
54+
}

common/src/main/java/com/firebase/ui/database/BaseObservableSnapshotArray.java renamed to common/src/main/java/com/firebase/ui/common/BaseObservableSnapshotArray.java

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.firebase.ui.database;
1+
package com.firebase.ui.common;
22

33
import android.support.annotation.CallSuper;
44
import android.support.annotation.NonNull;
@@ -8,18 +8,26 @@
88
import java.util.concurrent.CopyOnWriteArrayList;
99

1010
/**
11-
* TODO
11+
* Exposes a collection of {@link S} items in a database as a {@link List} of {@link E} objects.
12+
* To observe the list attach a {@link L} listener.
13+
*
1214
* @param <S> the snapshot class.
1315
* @param <L> the listener class.
1416
* @param <E> the model object class.
1517
*/
1618
public abstract class BaseObservableSnapshotArray<S, L, E> extends AbstractList<S> {
1719

1820
protected final List<L> mListeners = new CopyOnWriteArrayList<>();
19-
protected final BaseSnapshotParser<S, E> mParser;
21+
protected BaseSnapshotParser<S, E> mParser;
2022

2123
private boolean mHasDataChanged = false;
2224

25+
/**
26+
* Default constructor. Must set the {@link BaseSnapshotParser} before the first operation
27+
* or an exception will be thrown.
28+
*/
29+
public BaseObservableSnapshotArray() {}
30+
2331
/**
2432
* Create an BaseObservableSnapshotArray with a custom {@link BaseSnapshotParser}.
2533
*
@@ -48,7 +56,7 @@ protected void onDestroy() {
4856
}
4957

5058
/**
51-
* TODO
59+
* Attach a listener to this array.
5260
*/
5361
@CallSuper
5462
public L addChangeEventListener(@NonNull L listener) {
@@ -59,7 +67,8 @@ public L addChangeEventListener(@NonNull L listener) {
5967
}
6068

6169
/**
62-
* TODO
70+
* Remove a listener from the array. If no listeners remain, {@link #onDestroy()}
71+
* will be called.
6372
*/
6473
@CallSuper
6574
public void removeChangeEventListener(@NonNull L listener) {
@@ -72,7 +81,7 @@ public void removeChangeEventListener(@NonNull L listener) {
7281
}
7382

7483
/**
75-
* TODO
84+
* Remove all listeners from the array.
7685
*/
7786
@CallSuper
7887
public void removeAllListeners() {
@@ -81,20 +90,6 @@ public void removeAllListeners() {
8190
}
8291
}
8392

84-
protected abstract List<S> getSnapshots();
85-
86-
protected boolean hasDataChanged() {
87-
return mHasDataChanged;
88-
}
89-
90-
protected void setHasDataChanged(boolean hasDataChanged) {
91-
mHasDataChanged = hasDataChanged;
92-
}
93-
94-
protected BaseSnapshotParser<S, E> getSnapshotParser() {
95-
return mParser;
96-
}
97-
9893
/**
9994
* @return true if the array is listening for change events from the Firebase
10095
* database, false otherwise
@@ -116,6 +111,10 @@ public final boolean isListening(L listener) {
116111
* initialized this will throw an unchecked exception.
117112
*/
118113
public E getObject(int index) {
114+
if (mParser == null) {
115+
throw new IllegalStateException("getObject() called before snapshot parser set.");
116+
}
117+
119118
return mParser.parseSnapshot(get(index));
120119
}
121120

@@ -128,4 +127,23 @@ public S get(int index) {
128127
public int size() {
129128
return getSnapshots().size();
130129
}
130+
131+
// TODO(samstern): Do we need this?
132+
protected abstract List<S> getSnapshots();
133+
134+
protected boolean hasDataChanged() {
135+
return mHasDataChanged;
136+
}
137+
138+
protected void setHasDataChanged(boolean hasDataChanged) {
139+
mHasDataChanged = hasDataChanged;
140+
}
141+
142+
protected BaseSnapshotParser<S, E> getSnapshotParser() {
143+
return mParser;
144+
}
145+
146+
protected void setSnapshotParser(BaseSnapshotParser<S, E> parser) {
147+
mParser = parser;
148+
}
131149
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
package com.firebase.ui.database;
1+
package com.firebase.ui.common;
2+
23

34
public interface BaseSnapshotParser<S, T> {
5+
46
/**
57
* This method parses the Snapshot into the requested type.
68
*
79
* @param snapshot the Snapshot to extract the model from
810
* @return the model extracted from the DataSnapshot
911
*/
1012
T parseSnapshot(S snapshot);
13+
1114
}

common/src/main/java/com/firebase/ui/database/Preconditions.java renamed to common/src/main/java/com/firebase/ui/common/Preconditions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
package com.firebase.ui.database;
1+
package com.firebase.ui.common;
22

33
import android.support.annotation.RestrictTo;
44

55
/**
66
* Convenience class for checking argument conditions.
77
*/
88
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
9-
class Preconditions {
9+
public class Preconditions {
1010
public static <T> T checkNotNull(T o) {
1111
if (o == null) throw new IllegalArgumentException("Argument cannot be null.");
1212
return o;

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

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,35 @@
44

55
import com.google.firebase.database.DataSnapshot;
66

7-
import java.util.HashMap;
8-
import java.util.Map;
9-
107
/**
118
* An extension of {@link ObservableSnapshotArray} that caches the result of {@link #getObject(int)}
129
* so that repeated calls for the same key are not expensive (unless the underlying snapshot has
1310
* changed).
1411
*/
1512
public abstract class CachingObservableSnapshotArray<T> extends ObservableSnapshotArray<T> {
16-
private Map<String, T> mObjectCache = new HashMap<>();
13+
14+
private final CachingSnapshotParser<T> mCache;
1715

1816
/**
1917
* @see ObservableSnapshotArray#ObservableSnapshotArray(Class)
2018
*/
2119
public CachingObservableSnapshotArray(@NonNull Class<T> tClass) {
22-
super(tClass);
20+
this(new ClassSnapshotParser<>(tClass));
2321
}
2422

2523
/**
2624
* @see ObservableSnapshotArray#ObservableSnapshotArray(SnapshotParser)
2725
*/
2826
public CachingObservableSnapshotArray(@NonNull SnapshotParser<T> parser) {
29-
super(parser);
27+
super();
28+
29+
mCache = new CachingSnapshotParser<>(parser);
30+
setSnapshotParser(mCache);
3031
}
3132

3233
@Override
3334
public T getObject(int index) {
34-
String key = get(index).getKey();
35-
36-
// Return from the cache if possible, otherwise populate the cache and return
37-
if (mObjectCache.containsKey(key)) {
38-
return mObjectCache.get(key);
39-
} else {
40-
T object = super.getObject(index);
41-
mObjectCache.put(key, object);
42-
return object;
43-
}
35+
return mCache.parseSnapshot(get(index));
4436
}
4537

4638
@Override
@@ -53,20 +45,20 @@ protected void onDestroy() {
5345
@Deprecated
5446
protected void clearData() {
5547
getSnapshots().clear();
56-
mObjectCache.clear();
48+
mCache.clearData();
5749
}
5850

5951
protected DataSnapshot removeData(int index) {
6052
DataSnapshot snapshot = getSnapshots().remove(index);
6153
if (snapshot != null) {
62-
mObjectCache.remove(snapshot.getKey());
54+
mCache.invalidate(snapshot.getKey());
6355
}
6456

6557
return snapshot;
6658
}
6759

6860
protected void updateData(int index, DataSnapshot snapshot) {
6961
getSnapshots().set(index, snapshot);
70-
mObjectCache.remove(snapshot.getKey());
62+
mCache.invalidate(snapshot.getKey());
7163
}
7264
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.firebase.ui.database;
2+
3+
import com.firebase.ui.common.BaseCachingSnapshotParser;
4+
import com.firebase.ui.common.BaseSnapshotParser;
5+
import com.google.firebase.database.DataSnapshot;
6+
7+
/**
8+
* Implementation of {@link BaseCachingSnapshotParser} for {@link DataSnapshot}.
9+
*/
10+
public class CachingSnapshotParser<T> extends BaseCachingSnapshotParser<DataSnapshot, T> {
11+
12+
public CachingSnapshotParser(BaseSnapshotParser<DataSnapshot, T> innerParser) {
13+
super(innerParser);
14+
}
15+
16+
@Override
17+
public String getId(DataSnapshot snapshot) {
18+
return snapshot.getKey();
19+
}
20+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.google.firebase.database.DatabaseError;
66

77
public interface ChangeEventListener {
8+
89
/**
910
* The type of event received when a child has been updated.
1011
*/

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.support.annotation.NonNull;
44

5+
import com.firebase.ui.common.Preconditions;
56
import com.google.firebase.database.DataSnapshot;
67

78
/**

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.support.annotation.CallSuper;
44
import android.support.annotation.NonNull;
55

6+
import com.firebase.ui.common.BaseObservableSnapshotArray;
67
import com.google.firebase.database.DataSnapshot;
78
import com.google.firebase.database.DatabaseError;
89

@@ -17,6 +18,13 @@
1718
public abstract class ObservableSnapshotArray<E>
1819
extends BaseObservableSnapshotArray<DataSnapshot, ChangeEventListener, E> {
1920

21+
/**
22+
* Default constructor. Must set the snapshot parser before user.
23+
*/
24+
public ObservableSnapshotArray() {
25+
super();
26+
}
27+
2028
/**
2129
* Create an ObservableSnapshotArray where snapshots are parsed as objects of a particular
2230
* class.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.firebase.ui.database;
22

3+
import com.firebase.ui.common.BaseSnapshotParser;
34
import com.google.firebase.database.DataSnapshot;
45

56
public interface SnapshotParser<T> extends BaseSnapshotParser<DataSnapshot, T> {}

0 commit comments

Comments
 (0)