Skip to content

Commit bc81fdc

Browse files
falhassenglide-copybara-robot
authored andcommitted
Add an experimental plugin system for decorating OnPreDrawListener in Glide.
- This change introduces `GlidePlugins` to allow external code to provide a decorator function for `ViewTreeObserver.OnPreDrawListener` instances used by `ViewTarget` and `CustomViewTarget`. PiperOrigin-RevId: 825163004
1 parent 777b8b5 commit bc81fdc

File tree

5 files changed

+80
-4
lines changed

5 files changed

+80
-4
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.bumptech.glide;
2+
3+
import android.view.ViewTreeObserver.OnPreDrawListener;
4+
import java.util.function.Function;
5+
6+
/**
7+
* A class for holding static methods that are used to globally modify the behavior of Glide. This
8+
* class is used to allow apps to globally modify the behavior of Glide.
9+
*/
10+
public final class GlidePlugins {
11+
12+
private static Function<OnPreDrawListener, OnPreDrawListener> onPreDrawListenerDecorator = null;
13+
14+
/**
15+
* Sets a decorator to be applied to all {@link OnPreDrawListener}s created by Glide.
16+
*
17+
* <p>This is intended to be used by apps that want to globally modify all {@link
18+
* OnPreDrawListener}s created by Glide.
19+
*
20+
* <p>This is an experimental method that may be removed without warning in a future version.
21+
*/
22+
public static void experimentalSetOnPreDrawListenerDecorator(
23+
Function<OnPreDrawListener, OnPreDrawListener> decorator) {
24+
onPreDrawListenerDecorator = decorator;
25+
}
26+
27+
/**
28+
* Returns the {@link OnPreDrawListener} provided, possibly after being decorated by {@link
29+
* #experimentalSetOnPreDrawListenerDecorator(Function)}.
30+
*/
31+
public static OnPreDrawListener decorateOnPreDrawListener(OnPreDrawListener listener) {
32+
if (onPreDrawListenerDecorator == null) {
33+
return listener;
34+
}
35+
return onPreDrawListenerDecorator.apply(listener);
36+
}
37+
38+
private GlidePlugins() {}
39+
}

library/src/main/java/com/bumptech/glide/request/target/CustomViewTarget.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import androidx.annotation.NonNull;
1515
import androidx.annotation.Nullable;
1616
import androidx.annotation.VisibleForTesting;
17+
import com.bumptech.glide.GlidePlugins;
1718
import com.bumptech.glide.R;
1819
import com.bumptech.glide.request.Request;
1920
import com.bumptech.glide.request.transition.Transition;
@@ -299,7 +300,7 @@ static final class SizeDeterminer {
299300
private final List<SizeReadyCallback> cbs = new ArrayList<>();
300301
@Synthetic boolean waitForLayout;
301302

302-
@Nullable private SizeDeterminerLayoutListener layoutListener;
303+
@Nullable private ViewTreeObserver.OnPreDrawListener layoutListener;
303304

304305
SizeDeterminer(@NonNull View view) {
305306
this.view = view;
@@ -359,7 +360,8 @@ void getSize(@NonNull SizeReadyCallback cb) {
359360
}
360361
if (layoutListener == null) {
361362
ViewTreeObserver observer = view.getViewTreeObserver();
362-
layoutListener = new SizeDeterminerLayoutListener(this);
363+
layoutListener =
364+
GlidePlugins.decorateOnPreDrawListener(new SizeDeterminerLayoutListener(this));
363365
observer.addOnPreDrawListener(layoutListener);
364366
}
365367
}

library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import androidx.annotation.NonNull;
1515
import androidx.annotation.Nullable;
1616
import androidx.annotation.VisibleForTesting;
17+
import com.bumptech.glide.GlidePlugins;
1718
import com.bumptech.glide.R;
1819
import com.bumptech.glide.request.Request;
1920
import com.bumptech.glide.util.Preconditions;
@@ -324,7 +325,7 @@ static final class SizeDeterminer {
324325
private final List<SizeReadyCallback> cbs = new ArrayList<>();
325326
@Synthetic boolean waitForLayout;
326327

327-
@Nullable private SizeDeterminerLayoutListener layoutListener;
328+
@Nullable private ViewTreeObserver.OnPreDrawListener layoutListener;
328329

329330
SizeDeterminer(@NonNull View view) {
330331
this.view = view;
@@ -384,7 +385,8 @@ void getSize(@NonNull SizeReadyCallback cb) {
384385
}
385386
if (layoutListener == null) {
386387
ViewTreeObserver observer = view.getViewTreeObserver();
387-
layoutListener = new SizeDeterminerLayoutListener(this);
388+
layoutListener =
389+
GlidePlugins.decorateOnPreDrawListener(new SizeDeterminerLayoutListener(this));
388390
observer.addOnPreDrawListener(layoutListener);
389391
}
390392
}

library/src/test/java/com/bumptech/glide/request/target/CustomViewTargetTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static org.junit.Assert.assertEquals;
44
import static org.junit.Assert.assertFalse;
55
import static org.junit.Assert.assertNull;
6+
import static org.mockito.ArgumentMatchers.any;
67
import static org.mockito.ArgumentMatchers.anyInt;
78
import static org.mockito.ArgumentMatchers.eq;
89
import static org.mockito.Mockito.inOrder;
@@ -20,14 +21,17 @@
2021
import android.view.ViewGroup;
2122
import android.view.ViewGroup.LayoutParams;
2223
import android.view.ViewTreeObserver;
24+
import android.view.ViewTreeObserver.OnPreDrawListener;
2325
import android.widget.FrameLayout;
2426
import android.widget.LinearLayout;
2527
import androidx.annotation.NonNull;
2628
import androidx.annotation.Nullable;
29+
import com.bumptech.glide.GlidePlugins;
2730
import com.bumptech.glide.request.Request;
2831
import com.bumptech.glide.request.transition.Transition;
2932
import com.google.common.truth.Truth;
3033
import java.util.concurrent.atomic.AtomicInteger;
34+
import java.util.function.Function;
3135
import org.junit.After;
3236
import org.junit.Before;
3337
import org.junit.Test;
@@ -56,6 +60,7 @@ public class CustomViewTargetTest {
5660
private CustomViewTarget<View, Object> target;
5761
@Mock private SizeReadyCallback cb;
5862
@Mock private Request request;
63+
@Mock private Function<OnPreDrawListener, OnPreDrawListener> onPreDrawListenerDecorator;
5964
private AttachStateTarget attachStateTarget;
6065

6166
@Before
@@ -84,6 +89,7 @@ public void setUp() {
8489
@After
8590
public void tearDown() {
8691
CustomViewTarget.SizeDeterminer.maxDisplayLength = null;
92+
GlidePlugins.experimentalSetOnPreDrawListenerDecorator(null);
8793
}
8894

8995
@Test
@@ -591,6 +597,17 @@ public void onLoadStarted_withoutClearOnDetach_doesNotAddListener() {
591597
verify(request, never()).clear();
592598
}
593599

600+
@Test
601+
public void getSize_whenPreDrawListenerIsUsed_appliesDecorator() {
602+
when(onPreDrawListenerDecorator.apply(any(OnPreDrawListener.class)))
603+
.thenAnswer(invocation -> invocation.getArgument(0));
604+
GlidePlugins.experimentalSetOnPreDrawListenerDecorator(onPreDrawListenerDecorator);
605+
606+
target.getSize(cb);
607+
608+
verify(onPreDrawListenerDecorator).apply(any(OnPreDrawListener.class));
609+
}
610+
594611
@Test
595612
public void onLoadCleared_withoutClearOnDetach_doesNotRemoveListeners() {
596613
final AtomicInteger count = new AtomicInteger();

library/test/src/test/java/com/bumptech/glide/request/target/ViewTargetTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static com.google.common.truth.Truth.assertThat;
55
import static org.junit.Assert.assertEquals;
66
import static org.junit.Assert.assertNull;
7+
import static org.mockito.ArgumentMatchers.any;
78
import static org.mockito.ArgumentMatchers.anyInt;
89
import static org.mockito.ArgumentMatchers.eq;
910
import static org.mockito.Mockito.inOrder;
@@ -26,6 +27,7 @@
2627
import androidx.annotation.NonNull;
2728
import androidx.annotation.Nullable;
2829
import androidx.test.core.app.ApplicationProvider;
30+
import com.bumptech.glide.GlidePlugins;
2931
import com.bumptech.glide.request.Request;
3032
import com.bumptech.glide.request.transition.Transition;
3133
import com.bumptech.glide.tests.Util;
@@ -34,6 +36,7 @@
3436
import java.util.List;
3537
import java.util.Set;
3638
import java.util.concurrent.CopyOnWriteArrayList;
39+
import java.util.function.Function;
3740
import org.junit.After;
3841
import org.junit.Before;
3942
import org.junit.Test;
@@ -64,6 +67,7 @@ public class ViewTargetTest {
6467
private PreDrawShadowViewTreeObserver shadowObserver;
6568
@Mock private SizeReadyCallback cb;
6669
@Mock private Request request;
70+
@Mock private Function<OnPreDrawListener, OnPreDrawListener> onPreDrawListenerDecorator;
6771
private int sdkVersion;
6872
private AttachStateTarget attachStateTarget;
6973

@@ -83,6 +87,7 @@ public void setUp() {
8387
public void tearDown() {
8488
Util.setSdkVersionInt(sdkVersion);
8589
ViewTarget.SizeDeterminer.maxDisplayLength = null;
90+
GlidePlugins.experimentalSetOnPreDrawListenerDecorator(null);
8691
}
8792

8893
@Test
@@ -441,6 +446,17 @@ public void getSize_withWidthAndHeightEqualToPadding_doesNotCallSizeReady() {
441446
verify(cb, never()).onSizeReady(anyInt(), anyInt());
442447
}
443448

449+
@Test
450+
public void getSize_whenPreDrawListenerIsUsed_appliesDecorator() {
451+
when(onPreDrawListenerDecorator.apply(any(OnPreDrawListener.class)))
452+
.thenAnswer(invocation -> invocation.getArgument(0));
453+
GlidePlugins.experimentalSetOnPreDrawListenerDecorator(onPreDrawListenerDecorator);
454+
455+
target.getSize(cb);
456+
457+
verify(onPreDrawListenerDecorator).apply(any(OnPreDrawListener.class));
458+
}
459+
444460
private void setDisplayDimens(Integer width, Integer height) {
445461
WindowManager windowManager =
446462
(WindowManager)

0 commit comments

Comments
 (0)