Skip to content

Commit cbaaca7

Browse files
committed
Make it kinda actually work
Change-Id: I4c640d09a0c585f046df32b76b00bd48db94aacb
1 parent 5109b4c commit cbaaca7

File tree

3 files changed

+172
-51
lines changed

3 files changed

+172
-51
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ private void attachRecyclerViewAdapter() {
134134
// }
135135
// });
136136

137+
// TODO
138+
mArray.setAdapter(adapter);
139+
137140
// Scroll listener for infinite
138141
mRecyclerView.addOnScrollListener(new FirestoreInfiniteScrollListener(mManager, mArray));
139142

firestore/src/main/java/com/firebase/ui/firestore/FirestoreInfiniteArray.java

Lines changed: 142 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,27 @@
22

33
import android.support.annotation.NonNull;
44
import android.support.annotation.Nullable;
5+
import android.support.v7.widget.RecyclerView;
56
import android.util.Log;
67

7-
import com.firebase.ui.common.ChangeEventType;
8+
import com.google.android.gms.tasks.OnCompleteListener;
9+
import com.google.android.gms.tasks.Task;
810
import com.google.firebase.firestore.DocumentSnapshot;
9-
import com.google.firebase.firestore.FirebaseFirestoreException;
1011
import com.google.firebase.firestore.Query;
12+
import com.google.firebase.firestore.QuerySnapshot;
1113

1214
import java.util.ArrayList;
1315
import java.util.Collections;
1416
import java.util.List;
1517

18+
// TODO: There is no reason for this to be an OSA
1619
public class FirestoreInfiniteArray<T> extends ObservableSnapshotArray<T> {
1720

1821
private static final String TAG = "FirestoreInfiniteArray";
1922

2023
private SnapshotParser<T> mParser;
2124

25+
private RecyclerView.Adapter mAdapter;
2226
private Query mForwardQuery;
2327
private Query mReverseQuery;
2428

@@ -34,18 +38,58 @@ public FirestoreInfiniteArray(Query forwardQuery, Query reverseQuery, SnapshotPa
3438
mReverseQuery = reverseQuery;
3539

3640
Page page = new Page(0, queryAfter(null));
41+
page.load();
42+
3743
mPages.add(page);
3844
}
3945

40-
public void loadNextPage() {
41-
Page lastPage = getLastPage();
46+
public void setAdapter(RecyclerView.Adapter adapter) {
47+
// TODO: yikes
48+
mAdapter = adapter;
49+
}
50+
51+
public int getPagesLoaded() {
52+
int count = 0;
53+
for (Page page : mPages) {
54+
if (page.getState() == PageState.LOADED) {
55+
count++;
56+
}
57+
}
4258

43-
if (lastPage.getState() == PageState.LOADING) {
44-
Log.d(TAG, "Skipping double-load.");
59+
return count;
60+
}
61+
62+
public void unloadPage() {
63+
// Find first loaded page
64+
int firstLoaded = findFirstOfState(PageState.LOADED);
65+
if (firstLoaded != -1) {
66+
mPages.get(firstLoaded).unload();
67+
Log.d(TAG, "unloadPage: unloading page " + firstLoaded);
68+
Log.d(TAG, "unloadPage: new size = " + size());
69+
}
70+
}
71+
72+
public void loadPrevPage() {
73+
if (countState(PageState.LOADING) > 0) {
4574
return;
4675
}
4776

48-
int size = size();
77+
// Find first unloaded page
78+
int lastUnloaded = findLastOfState(PageState.UNLOADED);
79+
if (lastUnloaded != -1) {
80+
Log.d(TAG, "loadPrevPage: loading " + lastUnloaded);
81+
mPages.get(lastUnloaded).load();
82+
}
83+
84+
// TODO: What if we have to change the starting position of the next page
85+
}
86+
87+
public void loadNextPage() {
88+
if (countState(PageState.LOADING) > 0) {
89+
return;
90+
}
91+
92+
Page lastPage = getLastPage();
4993
DocumentSnapshot lastSnapshot = lastPage.getLast();
5094

5195
if (lastSnapshot == null) {
@@ -54,11 +98,65 @@ public void loadNextPage() {
5498
}
5599

56100
Query nextQuery = queryAfter(lastSnapshot);
57-
Log.d(TAG, "loadNextPage: sizeBefore=" + size + ", lastId=" + lastSnapshot.getId());
58-
Page nextPage = new Page(size, nextQuery);
101+
Log.d(TAG, "loadNextPage: loading page " + mPages.size());
102+
103+
// Add and start loading
104+
int nextPageIndex = mPages.size();
105+
Page nextPage = new Page(nextPageIndex, nextQuery);
59106
mPages.add(nextPage);
107+
nextPage.load();
60108
}
61109

110+
private void onPageLoaded(int index, int size) {
111+
int itemsBefore = 0;
112+
for (int i = 0; i < index; i++) {
113+
itemsBefore += mPages.get(i).size();
114+
}
115+
116+
mAdapter.notifyItemRangeInserted(itemsBefore, size);
117+
}
118+
119+
private void onPageUnloaded(int index, int size) {
120+
int itemsBefore = 0;
121+
for (int i = 0; i < index; i++) {
122+
itemsBefore += mPages.get(i).size();
123+
}
124+
125+
mAdapter.notifyItemRangeRemoved(itemsBefore, size);
126+
}
127+
128+
private int findFirstOfState(PageState state) {
129+
for (int i = 0; i < mPages.size(); i++) {
130+
Page page = mPages.get(i);
131+
if (page.getState() == state) {
132+
return i;
133+
}
134+
}
135+
136+
return -1;
137+
}
138+
139+
private int findLastOfState(PageState state) {
140+
for (int i = mPages.size() - 1; i >= 0; i--) {
141+
Page page = mPages.get(i);
142+
if (page.getState() == state) {
143+
return i;
144+
}
145+
}
146+
147+
return -1;
148+
}
149+
150+
private int countState(PageState state) {
151+
int count = 0;
152+
for (Page page : mPages) {
153+
if (page.getState() == state) {
154+
count++;
155+
}
156+
}
157+
158+
return count;
159+
}
62160

63161
@NonNull
64162
@Override
@@ -118,66 +216,60 @@ private Query queryAfter(@Nullable DocumentSnapshot snapshot) {
118216

119217
private enum PageState {
120218
LOADING,
121-
LOADED
219+
LOADED,
220+
UNLOADED
122221
}
123222

124-
private class Page implements ChangeEventListener {
223+
private class Page implements OnCompleteListener<QuerySnapshot> {
125224

126225
// TODO: state
127226

128-
private PageState mState = PageState.LOADING;
129-
130-
public final int mStartingPosition;
227+
private PageState mState;
228+
public final int mIndex;
131229
public final Query mQuery;
132-
public final FirestoreArray<T> mItems;
230+
231+
private DocumentSnapshot mFirstInPage;
133232

134233
private List<DocumentSnapshot> mSnapshots = new ArrayList<>();
135234

136-
public Page(int startingPosition, Query query) {
137-
mStartingPosition = startingPosition;
235+
public Page(int index, Query query) {
236+
mIndex = index;
138237
mQuery = query;
139238

140-
mItems = new FirestoreArray<>(query, mParser);
141-
mItems.addChangeEventListener(this);
239+
mState = PageState.UNLOADED;
142240
}
143241

144-
@Override
145-
public void onChildChanged(@NonNull ChangeEventType type,
146-
@NonNull DocumentSnapshot snapshot,
147-
int newIndex,
148-
int oldIndex) {
149-
switch (type) {
150-
// TODO: Implement all types
151-
case ADDED:
152-
int newIndexAdjusted = newIndex + mStartingPosition;
153-
int oldIndexAdjusted = oldIndex == -1
154-
? -1
155-
: oldIndex + mStartingPosition;
156-
157-
Log.d(TAG, "onChildAdded, old=" + oldIndexAdjusted + ", new=" + newIndexAdjusted);
158-
notifyOnChildChanged(type, snapshot, newIndexAdjusted, oldIndexAdjusted);
159-
mSnapshots.add(snapshot);
160-
break;
161-
case MOVED:
162-
break;
163-
case CHANGED:
164-
break;
165-
case REMOVED:
166-
break;
167-
}
242+
public void load() {
243+
// TODO: start and end
244+
mState = PageState.LOADING;
245+
mQuery.get().addOnCompleteListener(this);
168246
}
169247

170-
@Override
171-
public void onDataChanged() {
172-
// TODO
173-
Log.d(TAG, "onDataChanged");
174-
mState = PageState.LOADED;
248+
public void unload() {
249+
int size = mSnapshots.size();
250+
mSnapshots.clear();
251+
252+
onPageUnloaded(mIndex, size);
253+
mState = PageState.UNLOADED;
175254
}
176255

177256
@Override
178-
public void onError(@NonNull FirebaseFirestoreException e) {
179-
// TODO
257+
public void onComplete(@NonNull Task<QuerySnapshot> task) {
258+
// TODO: Better error handling
180259
mState = PageState.LOADED;
260+
261+
if (!task.isSuccessful()) {
262+
Log.w(TAG, "Failed to get page", task.getException());
263+
}
264+
265+
Log.d(TAG, "pageLoaded: " + mIndex);
266+
267+
// Add all snapshots
268+
mSnapshots.addAll(task.getResult().getDocuments());
269+
270+
// TODO
271+
// Range insert
272+
onPageLoaded(mIndex, mSnapshots.size());
181273
}
182274

183275
public PageState getState() {

firestore/src/main/java/com/firebase/ui/firestore/FirestoreInfiniteScrollListener.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.firebase.ui.firestore;
22

3+
import android.os.Handler;
34
import android.support.v7.widget.LinearLayoutManager;
45
import android.support.v7.widget.RecyclerView;
56

@@ -8,6 +9,8 @@ public class FirestoreInfiniteScrollListener extends RecyclerView.OnScrollListen
89
private LinearLayoutManager mManager;
910
private FirestoreInfiniteArray mArray;
1011

12+
private Handler mHandler = new Handler();
13+
1114
public FirestoreInfiniteScrollListener(LinearLayoutManager manager,
1215
FirestoreInfiniteArray array) {
1316
mManager = manager;
@@ -30,10 +33,33 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
3033

3134
// TODO: configurable "closeness"
3235
boolean movingDown = dy > 0;
36+
boolean closeToTop = (firstVisible <= 5);
3337
boolean closeToBottom = (totalSize - lastVisible) <= 5;
3438

3539
if (closeToBottom && movingDown) {
36-
mArray.loadNextPage();
40+
41+
mHandler.post(new Runnable() {
42+
@Override
43+
public void run() {
44+
mArray.loadNextPage();
45+
46+
// Unload top page.
47+
if (mArray.getPagesLoaded() >= 3 ) {
48+
mArray.unloadPage();
49+
}
50+
}
51+
});
52+
53+
} else if (closeToTop && !movingDown) {
54+
55+
mHandler.post(new Runnable() {
56+
@Override
57+
public void run() {
58+
// Load one page up
59+
mArray.loadPrevPage();
60+
}
61+
});
62+
3763
}
3864
}
3965

0 commit comments

Comments
 (0)