private void preload(int from, int to) { int start; int end; if (from < to) { start = Math.max(lastEnd, from); end = to; } else { start = to; end = Math.min(lastStart, from); } end = Math.min(totalItemCount, end); start = Math.min(totalItemCount, Math.max(0, start)); if (from < to) { // Increasing for (int i = start; i < end; i++) { preloadAdapterPosition(preloadModelProvider.getPreloadItems(i), i, true); } } else { // Decreasing for (int i = end - 1; i >= start; i--) { preloadAdapterPosition(preloadModelProvider.getPreloadItems(i), i, false); } } lastStart = start; lastEnd = end; }
private void preloadAdapterPosition(List<T> items, int position, boolean isIncreasing) { final int numItems = items.size(); if (isIncreasing) { for (int i = 0; i < numItems; ++i) { preloadItem(items.get(i), position, i); } } else { for (int i = numItems - 1; i >= 0; --i) { preloadItem(items.get(i), position, i); } } }
@Test public void testDontPreloadItemsRepeatedlyWhileIncreasing() { final AtomicInteger called = new AtomicInteger(); ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { @NonNull @Override public List<Object> getPreloadItems(int position) { final int current = called.getAndIncrement(); assertEquals(11 + current, position); return super.getPreloadItems(position); } }; ListPreloader<Object> preloader = new ListPreloader<>(requestManager, preloaderAdapter, preloaderAdapter, 10); preloader.onScroll(null, 1, 10, 30); preloader.onScroll(null, 4, 10, 30); assertEquals(13, called.get()); }
@Override public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount) { totalItemCount = totalCount; if (firstVisible > lastFirstVisible) { preload(firstVisible + visibleCount, true); } else if (firstVisible < lastFirstVisible) { preload(firstVisible, false); } lastFirstVisible = firstVisible; }
/** * Constructor that accepts interfaces for providing the dimensions of images to preload, the list * of models to preload for a given position, and the request to use to load images. * * @param preloadModelProvider Provides models to load and requests capable of loading them. * @param preloadDimensionProvider Provides the dimensions of images to load. * @param maxPreload Maximum number of items to preload. */ public RecyclerViewPreloader(@NonNull RequestManager requestManager, @NonNull PreloadModelProvider<T> preloadModelProvider, @NonNull PreloadSizeProvider<T> preloadDimensionProvider, int maxPreload) { ListPreloader<T> listPreloader = new ListPreloader<>(requestManager, preloadModelProvider, preloadDimensionProvider, maxPreload); recyclerScrollListener = new RecyclerToListViewScrollListener(listPreloader); }
@Override public GenericRequestBuilder getPreloadRequestBuilder(T item) { return getRequestBuilder(item); } };
@Override public int[] getPreloadSize(T item, int adapterPosition, int perItemPosition) { return getDimensions(item); } };
@Override public List<T> getPreloadItems(int position) { return getItems(position, position + 1); }
@Test public void testDontPreloadItemsRepeatedlyWhileDecreasing() { final AtomicInteger called = new AtomicInteger(); ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { @NonNull @Override public List<Object> getPreloadItems(int position) { if (position >= 20) { return Collections.emptyList(); } final int current = called.getAndIncrement(); assertEquals(19 - current, position); return super.getPreloadItems(position); } }; ListPreloader<Object> preloader = new ListPreloader<>(requestManager, preloaderAdapter, preloaderAdapter, 10); preloader.onScroll(null, 21, 10, 30); preloader.onScroll(null, 20, 10, 30); preloader.onScroll(null, 17, 10, 30); assertEquals(13, called.get()); }
@Override public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount) { totalItemCount = totalCount; if (firstVisible > lastFirstVisible) { preload(firstVisible + visibleCount, true); } else if (firstVisible < lastFirstVisible) { preload(firstVisible, false); } lastFirstVisible = firstVisible; }
@Test public void testGetItemsIsNeverCalledWithStartLessThanZero() { final AtomicBoolean called = new AtomicBoolean(false); final AtomicInteger calledCount = new AtomicInteger(); ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { @NonNull @Override public List<Object> getPreloadItems(int position) { if (position >= 17) { return Collections.emptyList(); } called.set(true); final int count = calledCount.getAndIncrement(); assertEquals(5 - count, position); return super.getPreloadItems(position); } }; ListPreloader<Object> preloader = new ListPreloader<>(requestManager, preloaderAdapter, preloaderAdapter, 10); preloader.onScroll(null, 7, 10, 30); preloader.onScroll(null, 6, 10, 30); assertTrue(called.get()); }
@Override public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount) { totalItemCount = totalCount; if (firstVisible > lastFirstVisible) { preload(firstVisible + visibleCount, true); } else if (firstVisible < lastFirstVisible) { preload(firstVisible, false); } lastFirstVisible = firstVisible; }
private void preloadAdapterPosition(List<T> items, int position, boolean isIncreasing) { final int numItems = items.size(); if (isIncreasing) { for (int i = 0; i < numItems; ++i) { preloadItem(items.get(i), position, i); } } else { for (int i = numItems - 1; i >= 0; --i) { preloadItem(items.get(i), position, i); } } }
private void preload(int from, int to) { int start; int end; if (from < to) { start = Math.max(lastEnd, from); end = to; } else { start = to; end = Math.min(lastStart, from); } end = Math.min(totalItemCount, end); start = Math.min(totalItemCount, Math.max(0, start)); if (from < to) { // Increasing for (int i = start; i < end; i++) { preloadAdapterPosition(this.preloadModelProvider.getPreloadItems(i), i, true); } } else { // Decreasing for (int i = end - 1; i >= start; i--) { preloadAdapterPosition(this.preloadModelProvider.getPreloadItems(i), i, false); } } lastStart = start; lastEnd = end; }
@Test public void testGetItemsIsCalledDecreasing() { final AtomicBoolean called = new AtomicBoolean(false); final AtomicInteger calledCount = new AtomicInteger(); ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { @NonNull @Override public List<Object> getPreloadItems(int position) { // Ignore the preload caused from us starting at the end if (position >= 40) { return Collections.emptyList(); } final int count = calledCount.getAndIncrement(); called.set(true); assertEquals(28 - count, position); return super.getPreloadItems(position); } }; ListPreloader<Object> preloader = new ListPreloader<>(requestManager, preloaderAdapter, preloaderAdapter, 10); preloader.onScroll(null, 30, 10, 40); preloader.onScroll(null, 29, 10, 40); assertTrue(called.get()); }
private void preloadAdapterPosition(List<T> items, int position, boolean isIncreasing) { final int numItems = items.size(); if (isIncreasing) { for (int i = 0; i < numItems; ++i) { preloadItem(items.get(i), position, i); } } else { for (int i = numItems - 1; i >= 0; --i) { preloadItem(items.get(i), position, i); } } }
private void preload(int from, int to) { int start; int end; if (from < to) { start = Math.max(lastEnd, from); end = to; } else { start = to; end = Math.min(lastStart, from); } end = Math.min(totalItemCount, end); start = Math.min(totalItemCount, Math.max(0, start)); if (from < to) { // Increasing for (int i = start; i < end; i++) { preloadAdapterPosition(this.preloadModelProvider.getPreloadItems(i), i, true); } } else { // Decreasing for (int i = end - 1; i >= start; i--) { preloadAdapterPosition(this.preloadModelProvider.getPreloadItems(i), i, false); } } lastStart = start; lastEnd = end; }