|
21 | 21 |
|
22 | 22 | package com.parse; |
23 | 23 |
|
24 | | -import android.annotation.SuppressLint; |
25 | 24 | import android.content.Context; |
26 | 25 | import android.database.DataSetObserver; |
27 | 26 | import android.graphics.drawable.Drawable; |
|
36 | 35 | import com.parse.ParseQuery.CachePolicy; |
37 | 36 |
|
38 | 37 | import java.util.ArrayList; |
| 38 | +import java.util.Collections; |
39 | 39 | import java.util.Iterator; |
40 | 40 | import java.util.List; |
| 41 | +import java.util.Set; |
41 | 42 | import java.util.WeakHashMap; |
| 43 | +import java.util.concurrent.ConcurrentHashMap; |
42 | 44 |
|
43 | 45 | import bolts.Capture; |
44 | 46 |
|
@@ -142,6 +144,9 @@ public static interface OnQueryLoadListener<T extends ParseObject> { |
142 | 144 |
|
143 | 145 | private List<T> objects = new ArrayList<>(); |
144 | 146 |
|
| 147 | + private Set<ParseQuery> runningQueries = Collections.newSetFromMap(new ConcurrentHashMap<ParseQuery, Boolean>()); |
| 148 | + |
| 149 | + |
145 | 150 | // Used to keep track of the pages of objects when using CACHE_THEN_NETWORK. When using this, |
146 | 151 | // the data will be flattened and put into the objects list. |
147 | 152 | private List<List<T>> objectPages = new ArrayList<>(); |
@@ -332,11 +337,19 @@ public void unregisterDataSetObserver(DataSetObserver observer) { |
332 | 337 | */ |
333 | 338 | public void clear() { |
334 | 339 | this.objectPages.clear(); |
| 340 | + cancelAllQueries(); |
335 | 341 | syncObjectsWithPages(); |
336 | 342 | this.notifyDataSetChanged(); |
337 | 343 | this.currentPage = 0; |
338 | 344 | } |
339 | 345 |
|
| 346 | + private void cancelAllQueries() { |
| 347 | + for (ParseQuery q : runningQueries) { |
| 348 | + q.cancel(); |
| 349 | + } |
| 350 | + runningQueries.clear(); |
| 351 | + } |
| 352 | + |
340 | 353 | /** |
341 | 354 | * Clears the table and loads the first page of objects asynchronously. This method is called |
342 | 355 | * automatically when this {@code Adapter} is attached to an {@code AdapterView}. |
@@ -365,22 +378,36 @@ private void loadObjects(final int page, final boolean shouldClear) { |
365 | 378 | // In the case of CACHE_THEN_NETWORK, two callbacks will be called. Using this flag to keep track, |
366 | 379 | final Capture<Boolean> firstCallBack = new Capture<>(true); |
367 | 380 |
|
| 381 | + runningQueries.add(query); |
| 382 | + |
| 383 | + // TODO convert to Tasks and CancellationTokens |
| 384 | + // (depends on https://github.com/ParsePlatform/Parse-SDK-Android/issues/6) |
368 | 385 | query.findInBackground(new FindCallback<T>() { |
369 | | - @SuppressLint("ShowToast") |
370 | 386 | @Override |
371 | 387 | public void done(List<T> foundObjects, ParseException e) { |
| 388 | + if (!runningQueries.contains(query)) { |
| 389 | + return; |
| 390 | + } |
| 391 | + // In the case of CACHE_THEN_NETWORK, two callbacks will be called. We can only remove the |
| 392 | + // query after the second callback. |
| 393 | + if (query.getCachePolicy() != CachePolicy.CACHE_THEN_NETWORK || |
| 394 | + (query.getCachePolicy() == CachePolicy.CACHE_THEN_NETWORK && !firstCallBack.get())) { |
| 395 | + runningQueries.remove(query); |
| 396 | + } |
372 | 397 | if ((!Parse.isLocalDatastoreEnabled() && |
373 | | - query.getCachePolicy() == CachePolicy.CACHE_ONLY) |
374 | | - && (e != null) && e.getCode() == ParseException.CACHE_MISS) { |
| 398 | + query.getCachePolicy() == CachePolicy.CACHE_ONLY) |
| 399 | + && (e != null) && e.getCode() == ParseException.CACHE_MISS) { |
375 | 400 | // no-op on cache miss |
376 | 401 | return; |
377 | 402 | } |
378 | 403 |
|
379 | | - if ((e != null) |
380 | | - && ((e.getCode() == ParseException.CONNECTION_FAILED) || (e.getCode() != ParseException.CACHE_MISS))) { |
| 404 | + if ((e != null) && ((e.getCode() == ParseException.CONNECTION_FAILED) || (e.getCode() != ParseException.CACHE_MISS))) { |
381 | 405 | hasNextPage = true; |
382 | 406 | } else if (foundObjects != null) { |
383 | 407 | if (shouldClear && firstCallBack.get()) { |
| 408 | + runningQueries.remove(query); |
| 409 | + cancelAllQueries(); |
| 410 | + runningQueries.add(query); // allow 2nd callback |
384 | 411 | objectPages.clear(); |
385 | 412 | objectPages.add(new ArrayList<T>()); |
386 | 413 | currentPage = page; |
@@ -432,7 +459,12 @@ private void syncObjectsWithPages() { |
432 | 459 | * changed. |
433 | 460 | */ |
434 | 461 | public void loadNextPage() { |
435 | | - this.loadObjects(currentPage + 1, false); |
| 462 | + if (objects.size() == 0 && runningQueries.size() == 0) { |
| 463 | + loadObjects(0, false); |
| 464 | + } |
| 465 | + else { |
| 466 | + loadObjects(currentPage + 1, false); |
| 467 | + } |
436 | 468 | } |
437 | 469 |
|
438 | 470 | /** |
|
0 commit comments