提交 5ebcfbd3 编写于 作者: D david

Support different target-sizes for list items

上级 28a34b61
...@@ -3,14 +3,26 @@ package com.bumptech.glide; ...@@ -3,14 +3,26 @@ package com.bumptech.glide;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.verification.VerificationMode;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
...@@ -21,21 +33,31 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -21,21 +33,31 @@ import java.util.concurrent.atomic.AtomicInteger;
@Config(manifest = Config.NONE, emulateSdk = 18) @Config(manifest = Config.NONE, emulateSdk = 18)
public class ListPreloaderTest { public class ListPreloaderTest {
@Mock
private BitmapRequestBuilder request;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test @Test
public void testGetItemsIsCalledIncreasing() { public void testGetItemsIsCalledIncreasing() {
final AtomicBoolean called = new AtomicBoolean(false); final AtomicBoolean called = new AtomicBoolean(false);
final AtomicInteger calledCount = new AtomicInteger();
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
called.set(true); called.set(true);
assertEquals(11, start); final int count = calledCount.getAndIncrement();
assertEquals(21, end); assertEquals(11 + count, position);
return super.getPreloadItems(start, end); return super.getPreloadItems(position);
} }
}; };
ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10); ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10);
preloader.onScroll(null, 1, 10, 30); preloader.onScroll(null, 1, 10, 30);
assertTrue(called.get()); assertEquals(10, calledCount.get());
} }
@Test @Test
...@@ -43,7 +65,7 @@ public class ListPreloaderTest { ...@@ -43,7 +65,7 @@ public class ListPreloaderTest {
final int toPreload = 10; final int toPreload = 10;
final List<Object> objects = new ArrayList<Object>(); final List<Object> objects = new ArrayList<Object>();
for (int i = 0; i < toPreload; i++) { for (int i = 0; i < toPreload; i++) {
objects.add(new Object()); objects.add(new Integer(i));
} }
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
...@@ -51,13 +73,13 @@ public class ListPreloaderTest { ...@@ -51,13 +73,13 @@ public class ListPreloaderTest {
public int expectedPosition; public int expectedPosition;
@Override @Override
public int[] getPreloadSize(Object item) { public int[] getPreloadSize(Object item, int adapterPostion, int itemPosition) {
return new int[]{10, 10}; return new int[]{10, 10};
} }
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
return objects; return objects.subList(position - 11, position + 1 - 11);
} }
@Override @Override
...@@ -68,24 +90,25 @@ public class ListPreloaderTest { ...@@ -68,24 +90,25 @@ public class ListPreloaderTest {
} }
}; };
ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter,
toPreload); toPreload);
preloader.onScroll(null, 1, 10, 30); preloader.onScroll(null, 1, 10, 20);
} }
@Test @Test
public void testGetItemsIsCalledDecreasing() { public void testGetItemsIsCalledDecreasing() {
final AtomicBoolean called = new AtomicBoolean(false); final AtomicBoolean called = new AtomicBoolean(false);
final AtomicInteger calledCount = new AtomicInteger();
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
// Ignore the preload caused from us starting at the end // Ignore the preload caused from us starting at the end
if (start == 40) { if (position >= 40) {
return Collections.emptyList(); return Collections.emptyList();
} }
final int count = calledCount.getAndIncrement();
called.set(true); called.set(true);
assertEquals(19, start); assertEquals(28 - count, position);
assertEquals(29, end); return super.getPreloadItems(position);
return super.getPreloadItems(start, end);
} }
}; };
ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10); ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10);
...@@ -106,16 +129,16 @@ public class ListPreloaderTest { ...@@ -106,16 +129,16 @@ public class ListPreloaderTest {
int expectedPosition = toPreload - 1; int expectedPosition = toPreload - 1;
@Override @Override
public int[] getPreloadSize(Object item) { public int[] getPreloadSize(Object item, int adapterPostion, int itemPosition) {
return new int[]{10, 10}; return new int[]{10, 10};
} }
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
if (start == 40) { if (position == 40) {
return Collections.emptyList(); return null;
} }
return objects; return objects.subList(position, position + 1);
} }
@Override @Override
...@@ -126,20 +149,21 @@ public class ListPreloaderTest { ...@@ -126,20 +149,21 @@ public class ListPreloaderTest {
} }
}; };
ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, toPreload); ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, toPreload);
preloader.onScroll(null, 30, 10, 40); preloader.onScroll(null, 30, 10, 10);
preloader.onScroll(null, 29, 10, 40); preloader.onScroll(null, 29, 10, 10);
} }
@Test @Test
public void testGetItemsIsNeverCalledWithEndGreaterThanTotalItems() { public void testGetItemsIsNeverCalledWithEndGreaterThanTotalItems() {
final AtomicBoolean called = new AtomicBoolean(false); final AtomicBoolean called = new AtomicBoolean(false);
final AtomicInteger calledCount = new AtomicInteger();
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
called.set(true); called.set(true);
assertEquals(26, start); final int count = calledCount.getAndIncrement();
assertEquals(30, end); assertEquals(26 + count, position);
return super.getPreloadItems(start, end); return super.getPreloadItems(position);
} }
}; };
ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10); ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10);
...@@ -150,16 +174,17 @@ public class ListPreloaderTest { ...@@ -150,16 +174,17 @@ public class ListPreloaderTest {
@Test @Test
public void testGetItemsIsNeverCalledWithStartLessThanZero() { public void testGetItemsIsNeverCalledWithStartLessThanZero() {
final AtomicBoolean called = new AtomicBoolean(false); final AtomicBoolean called = new AtomicBoolean(false);
final AtomicInteger calledCount = new AtomicInteger();
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
if (start == 17) { if (position >= 17) {
return Collections.emptyList(); return Collections.emptyList();
} }
called.set(true); called.set(true);
assertEquals(0, start); final int count = calledCount.getAndIncrement();
assertEquals(6, end); assertEquals(5 - count, position);
return super.getPreloadItems(start, end); return super.getPreloadItems(position);
} }
}; };
...@@ -174,16 +199,10 @@ public class ListPreloaderTest { ...@@ -174,16 +199,10 @@ public class ListPreloaderTest {
final AtomicInteger called = new AtomicInteger(); final AtomicInteger called = new AtomicInteger();
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
final int current = called.getAndIncrement(); final int current = called.getAndIncrement();
if (current == 0) { assertEquals(11 + current, position);
assertEquals(11, start); return super.getPreloadItems(position);
assertEquals(21, end);
} else if (current == 1) {
assertEquals(21, start);
assertEquals(24, end);
}
return super.getPreloadItems(start, end);
} }
}; };
...@@ -191,7 +210,7 @@ public class ListPreloaderTest { ...@@ -191,7 +210,7 @@ public class ListPreloaderTest {
preloader.onScroll(null, 1, 10, 30); preloader.onScroll(null, 1, 10, 30);
preloader.onScroll(null, 4, 10, 30); preloader.onScroll(null, 4, 10, 30);
assertEquals(2, called.get()); assertEquals(13, called.get());
} }
@Test @Test
...@@ -199,19 +218,13 @@ public class ListPreloaderTest { ...@@ -199,19 +218,13 @@ public class ListPreloaderTest {
final AtomicInteger called = new AtomicInteger(); final AtomicInteger called = new AtomicInteger();
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
if (start == 30) { if (position >= 20) {
return Collections.emptyList(); return Collections.emptyList();
} }
final int current = called.getAndIncrement(); final int current = called.getAndIncrement();
if (current == 0) { assertEquals(19 - current, position);
assertEquals(10, start); return super.getPreloadItems(position);
assertEquals(20, end);
} else if (current == 1) {
assertEquals(7, start);
assertEquals(10, end);
}
return super.getPreloadItems(start, end);
} }
}; };
...@@ -219,7 +232,91 @@ public class ListPreloaderTest { ...@@ -219,7 +232,91 @@ public class ListPreloaderTest {
preloader.onScroll(null, 21, 10, 30); preloader.onScroll(null, 21, 10, 30);
preloader.onScroll(null, 20, 10, 30); preloader.onScroll(null, 20, 10, 30);
preloader.onScroll(null, 17, 10, 30); preloader.onScroll(null, 17, 10, 30);
assertEquals(2, called.get()); assertEquals(13, called.get());
}
@Test
public void testMultipleItemsForPositionIncreasing() throws NoSuchFieldException {
final List<Object> objects = new ArrayList<Object>();
objects.add(new Object());
objects.add(new Object());
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
public int expectedPosition = (1 + 10) * 2;
@Override
public List<Object> getPreloadItems(int position) {
return objects;
}
@Override
public int[] getPreloadSize(Object item, int adapterPostion, int itemPosition) {
assertEquals(expectedPosition / 2, adapterPostion);
assertEquals(expectedPosition % 2, itemPosition);
expectedPosition++;
return itemPosition == 0 ? new int[]{10, 11} : new int[]{20, 21};
}
@Override
public GenericRequestBuilder getPreloadRequestBuilder(Object item) {
return request;
}
};
ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10);
Iterable<Integer> expected = Arrays.asList(10, 11, 20, 21, 10, 11, 20, 21);
preloader.onScroll(null, 1, 10, 1 + 10 + 2);
List<Integer> allValues = getTagetsSizes(request, times(4));
assertEquals(expected, allValues);
}
@Test
public void testMultipleItemsForPositionDecreasing() throws NoSuchFieldException {
final List<Object> objects = new ArrayList<Object>();
objects.add(new Object());
objects.add(new Object());
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
int expectedPosition = objects.size() * 2 - 1;
@Override
public List<Object> getPreloadItems(int position) {
return objects;
}
@Override
public int[] getPreloadSize(Object item, int adapterPostion, int itemPosition) {
assertEquals(expectedPosition / 2, adapterPostion);
assertEquals(expectedPosition % 2, itemPosition);
expectedPosition--;
return itemPosition == 0 ? new int[]{10, 11} : new int[]{20, 21};
}
@Override
public GenericRequestBuilder getPreloadRequestBuilder(Object item) {
return request;
}
};
ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10);
Iterable<Integer> expected = Arrays.asList(20, 21, 10, 11, 20, 21, 10, 11);
preloader.onScroll(null, 3, 2, 3 + 2);
preloader.onScroll(null, 2, 2, 3 + 2);
List<Integer> allValues = getTagetsSizes(request, times(4));
assertEquals(expected, allValues);
}
private List<Integer> getTagetsSizes(BitmapRequestBuilder requestBuilder, VerificationMode callVerificationMode) {
ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
ArgumentCaptor<Target> targetArgumentCaptor = ArgumentCaptor.forClass(Target.class);
SizeReadyCallback cb = mock(SizeReadyCallback.class);
VerificationMode mode = atLeastOnce();
verify(requestBuilder, mode).into(targetArgumentCaptor.capture());
for (Target target : targetArgumentCaptor.getAllValues()) {
target.getSize(cb);
}
verify(cb, mode).onSizeReady(integerArgumentCaptor.capture(), integerArgumentCaptor.capture());
return integerArgumentCaptor.getAllValues();
} }
@Test @Test
...@@ -230,8 +327,8 @@ public class ListPreloaderTest { ...@@ -230,8 +327,8 @@ public class ListPreloaderTest {
final HashSet<Object> loadedObjects = new HashSet<Object>(); final HashSet<Object> loadedObjects = new HashSet<Object>();
ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() { ListPreloaderAdapter preloaderAdapter = new ListPreloaderAdapter() {
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
return objects; return objects.subList(position - 11, position - 10);
} }
@Override @Override
...@@ -241,7 +338,8 @@ public class ListPreloaderTest { ...@@ -241,7 +338,8 @@ public class ListPreloaderTest {
} }
}; };
ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10); ListPreloader<Object> preloader = new ListPreloader<Object>(preloaderAdapter, preloaderAdapter, 10);
preloader.onScroll(null, 1, 10, 30);
preloader.onScroll(null, 1, 10, 13);
assertThat(loadedObjects).containsAllIn(objects); assertThat(loadedObjects).containsAllIn(objects);
} }
...@@ -252,8 +350,8 @@ public class ListPreloaderTest { ...@@ -252,8 +350,8 @@ public class ListPreloaderTest {
} }
@Override @Override
public List<Object> getPreloadItems(int start, int end) { public List<Object> getPreloadItems(int position) {
ArrayList<Object> result = new ArrayList<Object>(end - start); ArrayList<Object> result = new ArrayList<Object>(1);
Collections.fill(result, new Object()); Collections.fill(result, new Object());
return result; return result;
} }
...@@ -264,7 +362,7 @@ public class ListPreloaderTest { ...@@ -264,7 +362,7 @@ public class ListPreloaderTest {
} }
@Override @Override
public int[] getPreloadSize(Object item) { public int[] getPreloadSize(Object item, int adapterPostion, int itemPosition) {
return new int[]{100, 100}; return new int[]{100, 100};
} }
} }
......
...@@ -14,7 +14,7 @@ import java.util.Queue; ...@@ -14,7 +14,7 @@ import java.util.Queue;
* Loads a few resources ahead in the direction of scrolling in any {@link AbsListView} so that images are in the memory * Loads a few resources ahead in the direction of scrolling in any {@link AbsListView} so that images are in the memory
* cache just before the corresponding view in created in the list. Gives the appearance of an infinitely large image * cache just before the corresponding view in created in the list. Gives the appearance of an infinitely large image
* cache, depending on scrolling speed, cpu speed, and cache size. * cache, depending on scrolling speed, cpu speed, and cache size.
* * <p/>
* <p> * <p>
* Must be set using {@link AbsListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)}, or have its * Must be set using {@link AbsListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)}, or have its
* corresponding methods called from another {@link android.widget.AbsListView.OnScrollListener} to function. * corresponding methods called from another {@link android.widget.AbsListView.OnScrollListener} to function.
...@@ -25,7 +25,7 @@ import java.util.Queue; ...@@ -25,7 +25,7 @@ import java.util.Queue;
public class ListPreloader<T> implements AbsListView.OnScrollListener { public class ListPreloader<T> implements AbsListView.OnScrollListener {
private final int maxPreload; private final int maxPreload;
private final PreloadTargetQueue preloadTargetQueue; protected final PreloadTargetQueue preloadTargetQueue;
private final PreloadModelProvider<T> preloadModelProvider; private final PreloadModelProvider<T> preloadModelProvider;
private final PreloadSizeProvider<T> preloadDimensionProvider; private final PreloadSizeProvider<T> preloadDimensionProvider;
...@@ -38,6 +38,7 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -38,6 +38,7 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
/** /**
* An implementation of PreloadModelProvider should provide all the models that should be preloaded. * An implementation of PreloadModelProvider should provide all the models that should be preloaded.
*
* @param <U> The type of the model being preloaded. * @param <U> The type of the model being preloaded.
*/ */
public interface PreloadModelProvider<U> { public interface PreloadModelProvider<U> {
...@@ -45,22 +46,19 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -45,22 +46,19 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
/** /**
* Returns a non null list of all models that need to be loaded for the list to display adapter items in * Returns a non null list of all models that need to be loaded for the list to display adapter items in
* positions between {@code start} and {@code end}. * positions between {@code start} and {@code end}.
* * <p/>
* <p> * <p>
* A list of any size can be returned so there can be multiple models per adapter position. * A list of any size can be returned so there can be multiple models per adapter position.
* </p> * </p>
* *
* @param start The smallest adapter position. Will be {@code >= 0 && < adapter.getCount() && * @param position The adapter position.
* <= end}
* @param end The largest adapter position. Will be {@code >= 0 && < adapter.getCount && >=
* start}
*/ */
List<U> getPreloadItems(int start, int end); List<U> getPreloadItems(int position);
/** /**
* Returns a non null {@link com.bumptech.glide.GenericRequestBuilder} for a given item. Must exactly match * Returns a non null {@link com.bumptech.glide.GenericRequestBuilder} for a given item. Must exactly match
* the request used to load the resource in the list. * the request used to load the resource in the list.
* * <p/>
* <p> * <p>
* The target and context will be provided by the preloader. * The target and context will be provided by the preloader.
* </p> * </p>
...@@ -81,40 +79,60 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -81,40 +79,60 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
/** /**
* Returns the size of the view in the list where the resources will be displayed in pixels in the format * Returns the size of the view in the list where the resources will be displayed in pixels in the format
* [x, y], or {@code null} if no size is currently available. * [x, y], or {@code null} if no size is currently available.
* * <p/>
* <p> * <p>
* Note - The dimensions returned here must precisely match those of the view in the list. * Note - The dimensions returned here must precisely match those of the view in the list.
* </p> * </p>
* *
* @param item A model * @param item A model
*/ */
int[] getPreloadSize(T item); int[] getPreloadSize(T item, int adapterPosition, int perItemPosition);
} }
/** /**
* Constructor for {@link com.bumptech.glide.ListPreloader} that requires users to subclass and override * Constructor for {@link com.bumptech.glide.ListPreloader} that requires users to subclass and override
* the {@link #getItems(int, int)} and {@link #getRequestBuilder(Object)} methods. * the {@link #getItems(int, int)} and {@link #getRequestBuilder(Object)} methods.
* *
* @param maxPreload Maximum number of items to preload.
* @deprecated Use {@link #ListPreloader(com.bumptech.glide.ListPreloader.PreloadModelProvider, * @deprecated Use {@link #ListPreloader(com.bumptech.glide.ListPreloader.PreloadModelProvider,
* com.bumptech.glide.ListPreloader.PreloadSizeProvider, int)} instead. This constructor will be removed in Glide * com.bumptech.glide.ListPreloader.PreloadSizeProvider, int)} instead. This constructor will be removed in Glide
* 4.0. * 4.0.
* @param maxPreload Maximum number of items to preload.
*/ */
@Deprecated @Deprecated
public ListPreloader(int maxPreload) { public ListPreloader(int maxPreload) {
this(null, null, maxPreload); this.preloadModelProvider = new PreloadModelProvider<T>() {
@Override
public List<T> getPreloadItems(int position) {
return getItems(position, position + 1);
}
@Override
public GenericRequestBuilder getPreloadRequestBuilder(T item) {
return getRequestBuilder(item);
}
};
this.preloadDimensionProvider = new PreloadSizeProvider<T>() {
@Override
public int[] getPreloadSize(T item, int adapterPosition, int perItemPosition) {
return getDimensions(item);
}
};
this.maxPreload = maxPreload;
preloadTargetQueue = new PreloadTargetQueue(maxPreload + 1);
} }
/** /**
* Constructor for {@link com.bumptech.glide.ListPreloader} that accepts interfaces for providing the dimensions of * Constructor for {@link com.bumptech.glide.ListPreloader} 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. * 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 preloadModelProvider Provides models to load and requests capable of loading them.
* @param preloadDimensionProvider Provides the dimensions of images to load. * @param preloadDimensionProvider Provides the dimensions of images to load.
* @param maxPreload Maximum number of items to preload. * @param maxPreload Maximum number of items to preload.
*/ */
public ListPreloader(PreloadModelProvider<T> preloadModelProvider, public ListPreloader(PreloadModelProvider<T> preloadModelProvider,
PreloadSizeProvider<T> preloadDimensionProvider, int maxPreload) { PreloadSizeProvider<T> preloadDimensionProvider, int maxPreload) {
this.preloadModelProvider = preloadModelProvider; this.preloadModelProvider = preloadModelProvider;
this.preloadDimensionProvider = preloadDimensionProvider; this.preloadDimensionProvider = preloadDimensionProvider;
this.maxPreload = maxPreload; this.maxPreload = maxPreload;
...@@ -128,7 +146,7 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -128,7 +146,7 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
@Override @Override
public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, public void onScroll(AbsListView absListView, int firstVisible, int visibleCount,
int totalCount) { int totalCount) {
totalItemCount = totalCount; totalItemCount = totalCount;
if (firstVisible > lastFirstVisible) { if (firstVisible > lastFirstVisible) {
preload(firstVisible + visibleCount, true); preload(firstVisible + visibleCount, true);
...@@ -140,67 +158,59 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -140,67 +158,59 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
/** /**
* Returns the size of the view in the list where the resources will be displayed. * Returns the size of the view in the list where the resources will be displayed.
* * <p/>
* <p> * <p>
* Note - The size returned here must precisely match those of the view in the list. * Note - The size returned here must precisely match those of the view in the list.
* </p> * </p>
* *
* @deprecated Use {@link com.bumptech.glide.ListPreloader.PreloadSizeProvider} instead. This method will be removed
* in Glide 4.0.
* @param item A model * @param item A model
* @return The size of the view where the item will be displayed * @return The size of the view where the item will be displayed
* @deprecated Use {@link com.bumptech.glide.ListPreloader.PreloadSizeProvider} instead. This method will be removed
* in Glide 4.0.
*/ */
@Deprecated @Deprecated
protected int[] getDimensions(T item) { protected int[] getDimensions(T item) {
if (preloadDimensionProvider == null) { throw new IllegalStateException("You must either provide a PreloadDimensionProvider or override "
throw new IllegalStateException("You must either provide a PreloadDimensionProvider or override getSize9)"); + "getDimensions()");
}
return this.preloadDimensionProvider.getPreloadSize(item);
} }
/** /**
* Returns a non null list of all models that need to be loaded for the list to display adapter items * Returns a non null list of all models that need to be loaded for the list to display adapter items
* between {@code start} and {@code end}. * between {@code start} and {@code end}.
* * <p/>
* <p> * <p>
* A list of any size can be returned so there can be multiple models per adapter position. * A list of any size can be returned so there can be multiple models per adapter position.
* </p> * </p>
* *
* @deprecated Use {@link com.bumptech.glide.ListPreloader.PreloadModelProvider} instead. This method will be
* removed in Glide 4.0.
* @param start The smallest adapter position. Will be {@code >= 0 && < adapter.getCount() && * @param start The smallest adapter position. Will be {@code >= 0 && < adapter.getCount() &&
* <= end} * <= end}
* @param end The largest adapter position. Will be {@code >= 0 && < adapter.getCount && >= * @param end The largest adapter position. Will be {@code >= 0 && < adapter.getCount && >=
* start} * start}
* @deprecated Use {@link com.bumptech.glide.ListPreloader.PreloadModelProvider} instead. This method will be
* removed in Glide 4.0.
*/ */
@Deprecated @Deprecated
protected List<T> getItems(int start, int end) { protected List<T> getItems(int start, int end) {
if (preloadModelProvider == null) { throw new IllegalStateException("You must either provide a PreloadModelProvider or override getItems()");
throw new IllegalStateException("You must either provide a PreloadModelProvider or override getItems()");
}
return this.preloadModelProvider.getPreloadItems(start, end);
} }
/** /**
* Returns a non null {@link com.bumptech.glide.GenericRequestBuilder} for a given item. Must exactly match the * Returns a non null {@link com.bumptech.glide.GenericRequestBuilder} for a given item. Must exactly match the
* request used to load the resource in the list. * request used to load the resource in the list.
* * <p/>
* <p> * <p>
* The target and context will be provided by the preloader. * The target and context will be provided by the preloader.
* </p> * </p>
* *
* @param item The model to load.
* @deprecated Use {@link com.bumptech.glide.ListPreloader.PreloadModelProvider} instead. This method will be * @deprecated Use {@link com.bumptech.glide.ListPreloader.PreloadModelProvider} instead. This method will be
* removed in Glide 4.0. * removed in Glide 4.0.
* @param item The model to load.
*/ */
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Deprecated @Deprecated
protected GenericRequestBuilder getRequestBuilder(T item) { protected GenericRequestBuilder getRequestBuilder(T item) {
if (preloadModelProvider == null) { throw new IllegalStateException("You must either provide a PreloadModelProvider, or override "
throw new IllegalStateException("You must either provide a PreloadModelProvider, or override " + "getRequestBuilder()");
+ "getRequestBuilder()");
}
return this.preloadModelProvider.getPreloadRequestBuilder(item);
} }
private void preload(int start, boolean increasing) { private void preload(int start, boolean increasing) {
...@@ -223,18 +233,18 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -223,18 +233,18 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
} }
end = Math.min(totalItemCount, end); end = Math.min(totalItemCount, end);
start = Math.min(totalItemCount, Math.max(0, start)); start = Math.min(totalItemCount, Math.max(0, start));
List<T> items = getItems(start, end); // List<T> items = getItems(start, end);
if (from < to) { if (from < to) {
// Increasing // Increasing
final int numItems = items.size(); // final int numItems = items.size();
for (int i = 0; i < numItems; i++) { for (int i = start; i < end; i++) {
preloadItem(items, i); preloadItem(this.preloadModelProvider.getPreloadItems(i), i, true);
} }
} else { } else {
// Decreasing // Decreasing
for (int i = items.size() - 1; i >= 0; i--) { for (int i = end - 1; i >= start; i--) {
preloadItem(items, i); preloadItem(this.preloadModelProvider.getPreloadItems(i), i, false);
} }
} }
...@@ -242,12 +252,25 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -242,12 +252,25 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
lastEnd = end; lastEnd = end;
} }
private void preloadItem(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);
}
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void preloadItem(List<T> items, int position) { private void preloadItem(T item, int position, int i) {
final T item = items.get(position); final int[] dimensions = this.preloadDimensionProvider.getPreloadSize(item, position, i);
final int[] dimensions = getDimensions(item);
if (dimensions != null) { if (dimensions != null) {
getRequestBuilder(item).into(preloadTargetQueue.next(dimensions[0], dimensions[1])); GenericRequestBuilder preloadRequestBuilder = this.preloadModelProvider.getPreloadRequestBuilder(item);
preloadRequestBuilder.into(preloadTargetQueue.next(dimensions[0], dimensions[1]));
} }
} }
...@@ -257,7 +280,7 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -257,7 +280,7 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
} }
} }
private static final class PreloadTargetQueue { protected static final class PreloadTargetQueue {
private final Queue<PreloadTarget> queue; private final Queue<PreloadTarget> queue;
public PreloadTargetQueue(int size) { public PreloadTargetQueue(int size) {
...@@ -283,7 +306,7 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener { ...@@ -283,7 +306,7 @@ public class ListPreloader<T> implements AbsListView.OnScrollListener {
@Override @Override
public void onResourceReady(Object resource, public void onResourceReady(Object resource,
GlideAnimation<? super Object> glideAnimation) { GlideAnimation<? super Object> glideAnimation) {
// Do nothing. // Do nothing.
} }
......
...@@ -24,7 +24,7 @@ public class FixedPreloadSizeProvider<T> implements ListPreloader.PreloadSizePro ...@@ -24,7 +24,7 @@ public class FixedPreloadSizeProvider<T> implements ListPreloader.PreloadSizePro
} }
@Override @Override
public int[] getPreloadSize(T item) { public int[] getPreloadSize(T item, int adapterPosition, int itemPosition) {
return Arrays.copyOf(this.size, this.size.length); return Arrays.copyOf(this.size, this.size.length);
} }
} }
...@@ -38,7 +38,7 @@ public class ViewPreloadSizeProvider<T> implements ListPreloader.PreloadSizeProv ...@@ -38,7 +38,7 @@ public class ViewPreloadSizeProvider<T> implements ListPreloader.PreloadSizeProv
} }
@Override @Override
public int[] getPreloadSize(T item) { public int[] getPreloadSize(T item, int adapterPosition, int itemPosition) {
if (size == null) { if (size == null) {
return null; return null;
} else { } else {
......
...@@ -171,8 +171,8 @@ public class FlickrPhotoGrid extends Fragment implements PhotoViewer { ...@@ -171,8 +171,8 @@ public class FlickrPhotoGrid extends Fragment implements PhotoViewer {
} }
@Override @Override
public List<Photo> getPreloadItems(int start, int end) { public List<Photo> getPreloadItems(int position) {
return photos.subList(start, end); return photos.subList(position, position + 1);
} }
@Override @Override
......
...@@ -168,8 +168,8 @@ public class FlickrPhotoList extends Fragment implements PhotoViewer { ...@@ -168,8 +168,8 @@ public class FlickrPhotoList extends Fragment implements PhotoViewer {
} }
@Override @Override
public List<Photo> getPreloadItems(int start, int end) { public List<Photo> getPreloadItems(int position) {
return photos.subList(start, end); return photos.subList(position, position + 1);
} }
@Override @Override
......
...@@ -91,7 +91,7 @@ public class MainActivity extends Activity implements Api.Monitor { ...@@ -91,7 +91,7 @@ public class MainActivity extends Activity implements Api.Monitor {
private Api.GifResult[] results = EMPTY_RESULTS; private Api.GifResult[] results = EMPTY_RESULTS;
public GifAdapter(Activity activity, DrawableRequestBuilder<Api.GifResult> requestBuilder, public GifAdapter(Activity activity, DrawableRequestBuilder<Api.GifResult> requestBuilder,
ViewPreloadSizeProvider<Api.GifResult> preloadSizeProvider) { ViewPreloadSizeProvider<Api.GifResult> preloadSizeProvider) {
this.activity = activity; this.activity = activity;
this.requestBuilder = requestBuilder; this.requestBuilder = requestBuilder;
this.preloadSizeProvider = preloadSizeProvider; this.preloadSizeProvider = preloadSizeProvider;
...@@ -155,11 +155,9 @@ public class MainActivity extends Activity implements Api.Monitor { ...@@ -155,11 +155,9 @@ public class MainActivity extends Activity implements Api.Monitor {
} }
@Override @Override
public List<Api.GifResult> getPreloadItems(int start, int end) { public List<Api.GifResult> getPreloadItems(int position) {
List<Api.GifResult> items = new ArrayList<Api.GifResult>(end - start); List<Api.GifResult> items = new ArrayList<Api.GifResult>(1);
for (int i = start; i < end; i++) { items.add(getItem(position));
items.add(getItem(i));
}
return items; return items;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册