Skip to content

Commit 8e08336

Browse files
committed
Actual bidirectional unloading
Change-Id: Id78e7ceee80b670424de4c93a5be2e819aac6fbb
1 parent cbaaca7 commit 8e08336

File tree

2 files changed

+75
-37
lines changed

2 files changed

+75
-37
lines changed

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

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class FirestoreInfiniteArray<T> extends ObservableSnapshotArray<T> {
3030

3131
private List<Page> mPages = new ArrayList<>();
3232

33+
// TODO: I am not using reverse query at all
3334
public FirestoreInfiniteArray(Query forwardQuery, Query reverseQuery, SnapshotParser<T> parser) {
3435
super(parser);
3536

@@ -59,13 +60,20 @@ public int getPagesLoaded() {
5960
return count;
6061
}
6162

62-
public void unloadPage() {
63+
public void unloadTopPage() {
6364
// Find first loaded page
6465
int firstLoaded = findFirstOfState(PageState.LOADED);
6566
if (firstLoaded != -1) {
6667
mPages.get(firstLoaded).unload();
67-
Log.d(TAG, "unloadPage: unloading page " + firstLoaded);
68-
Log.d(TAG, "unloadPage: new size = " + size());
68+
Log.d(TAG, "UNLOADING " + firstLoaded);
69+
}
70+
}
71+
72+
public void unloadBottomPage() {
73+
int lastLoaded = findLastOfState(PageState.LOADED);
74+
if (lastLoaded != -1) {
75+
mPages.get(lastLoaded).unload();
76+
Log.d(TAG, "UNLOADING " + lastLoaded);
6977
}
7078
}
7179

@@ -74,37 +82,54 @@ public void loadPrevPage() {
7482
return;
7583
}
7684

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-
}
85+
// Load the last UNLOADED page before the middle "core" of LOADED pages
86+
int firstLoaded = findFirstOfState(PageState.LOADED);
87+
int lastUnloadedBefore = findLastOfState(PageState.UNLOADED, firstLoaded);
8388

84-
// TODO: What if we have to change the starting position of the next page
89+
if (lastUnloadedBefore != -1) {
90+
Log.d(TAG, "RELOADING " + lastUnloadedBefore);
91+
mPages.get(lastUnloadedBefore).load();
92+
}
8593
}
8694

8795
public void loadNextPage() {
8896
if (countState(PageState.LOADING) > 0) {
8997
return;
9098
}
9199

92-
Page lastPage = getLastPage();
93-
DocumentSnapshot lastSnapshot = lastPage.getLast();
100+
// There are two cases here
101+
// 1. Need to load a whole new page
102+
// 2. Need to load an UNLOADED bottom page
94103

95-
if (lastSnapshot == null) {
96-
Log.w(TAG, "Skipping load because last snapshot is null!");
97-
return;
98-
}
104+
int lastLoaded = findLastOfState(PageState.LOADED);
99105

100-
Query nextQuery = queryAfter(lastSnapshot);
101-
Log.d(TAG, "loadNextPage: loading page " + mPages.size());
106+
if (lastLoaded == mPages.size() - 1) {
107+
// Case 1: Load a new page at the bottom
108+
Page lastPage = getLastPage();
109+
DocumentSnapshot lastSnapshot = lastPage.getLast();
110+
111+
// Reached the end, no more items to show
112+
if (lastSnapshot == null) {
113+
return;
114+
}
115+
116+
Query nextQuery = queryAfter(lastSnapshot);
117+
Log.d(TAG, "LOADING " + mPages.size());
118+
119+
// Add and start loading
120+
int nextPageIndex = mPages.size();
121+
Page nextPage = new Page(nextPageIndex, nextQuery);
122+
mPages.add(nextPage);
123+
nextPage.load();
124+
} else {
125+
// Case 2: Need to load a previously unloaded page
126+
// Find the first UNLOADED page after the middle "core" of loaded pages
127+
int firstUnloadedAfter = findFirstOfState(PageState.UNLOADED, lastLoaded);
128+
129+
Log.d(TAG, "RELOADING " + firstUnloadedAfter);
130+
mPages.get(firstUnloadedAfter).load();
131+
}
102132

103-
// Add and start loading
104-
int nextPageIndex = mPages.size();
105-
Page nextPage = new Page(nextPageIndex, nextQuery);
106-
mPages.add(nextPage);
107-
nextPage.load();
108133
}
109134

110135
private void onPageLoaded(int index, int size) {
@@ -126,7 +151,11 @@ private void onPageUnloaded(int index, int size) {
126151
}
127152

128153
private int findFirstOfState(PageState state) {
129-
for (int i = 0; i < mPages.size(); i++) {
154+
return findFirstOfState(state, 0);
155+
}
156+
157+
private int findFirstOfState(PageState state, int startingAt) {
158+
for (int i = startingAt; i < mPages.size(); i++) {
130159
Page page = mPages.get(i);
131160
if (page.getState() == state) {
132161
return i;
@@ -137,7 +166,11 @@ private int findFirstOfState(PageState state) {
137166
}
138167

139168
private int findLastOfState(PageState state) {
140-
for (int i = mPages.size() - 1; i >= 0; i--) {
169+
return findLastOfState(state, mPages.size() - 1);
170+
}
171+
172+
private int findLastOfState(PageState state, int endingAt) {
173+
for (int i = endingAt; i >= 0; i--) {
141174
Page page = mPages.get(i);
142175
if (page.getState() == state) {
143176
return i;
@@ -178,9 +211,8 @@ public DocumentSnapshot getSnapshot(int index) {
178211
remaining -= page.size();
179212
}
180213

181-
// TODO
182-
Log.e(TAG, "Requested bad index: " + index);
183-
return null;
214+
throw new IllegalArgumentException(
215+
"Requested non-existent index: " + index + ", size=" + size());
184216
}
185217

186218
@NonNull
@@ -222,11 +254,10 @@ private enum PageState {
222254

223255
private class Page implements OnCompleteListener<QuerySnapshot> {
224256

225-
// TODO: state
226-
257+
// TODO: Does the Page really need to track its own index?
227258
private PageState mState;
228-
public final int mIndex;
229-
public final Query mQuery;
259+
private final int mIndex;
260+
private final Query mQuery;
230261

231262
private DocumentSnapshot mFirstInPage;
232263

@@ -262,12 +293,11 @@ public void onComplete(@NonNull Task<QuerySnapshot> task) {
262293
Log.w(TAG, "Failed to get page", task.getException());
263294
}
264295

265-
Log.d(TAG, "pageLoaded: " + mIndex);
296+
Log.d(TAG, "LOADED " + mIndex);
266297

267298
// Add all snapshots
268299
mSnapshots.addAll(task.getResult().getDocuments());
269300

270-
// TODO
271301
// Range insert
272302
onPageLoaded(mIndex, mSnapshots.size());
273303
}

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class FirestoreInfiniteScrollListener extends RecyclerView.OnScrollListen
1111

1212
private Handler mHandler = new Handler();
1313

14+
// TODO: This could take the same options as the Array
1415
public FirestoreInfiniteScrollListener(LinearLayoutManager manager,
1516
FirestoreInfiniteArray array) {
1617
mManager = manager;
@@ -31,8 +32,9 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
3132

3233
int totalSize = mArray.size();
3334

34-
// TODO: configurable "closeness"
35+
// TODO: configurable "closeness" and number of pages to keep
3536
boolean movingDown = dy > 0;
37+
boolean movingUp = !movingDown;
3638
boolean closeToTop = (firstVisible <= 5);
3739
boolean closeToBottom = (totalSize - lastVisible) <= 5;
3840

@@ -41,22 +43,28 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
4143
mHandler.post(new Runnable() {
4244
@Override
4345
public void run() {
46+
// Load one page down
4447
mArray.loadNextPage();
4548

4649
// Unload top page.
4750
if (mArray.getPagesLoaded() >= 3 ) {
48-
mArray.unloadPage();
51+
mArray.unloadTopPage();
4952
}
5053
}
5154
});
5255

53-
} else if (closeToTop && !movingDown) {
56+
} else if (closeToTop && movingUp) {
5457

5558
mHandler.post(new Runnable() {
5659
@Override
5760
public void run() {
5861
// Load one page up
5962
mArray.loadPrevPage();
63+
64+
// Unload bottom page
65+
if (mArray.getPagesLoaded() >= 3) {
66+
mArray.unloadBottomPage();
67+
}
6068
}
6169
});
6270

0 commit comments

Comments
 (0)