|
22 | 22 | import com.facebook.react.bridge.WritableMap; |
23 | 23 | import com.facebook.react.bridge.WritableNativeMap; |
24 | 24 | import com.facebook.react.common.build.ReactBuildConfig; |
| 25 | +import com.facebook.react.config.ReactFeatureFlags; |
25 | 26 | import com.facebook.react.uimanager.FabricViewStateManager; |
26 | 27 | import com.facebook.react.uimanager.PixelUtil; |
27 | 28 | import com.facebook.react.uimanager.UIManagerHelper; |
@@ -68,34 +69,49 @@ void onScroll( |
68 | 69 | private static boolean mSmoothScrollDurationInitialized = false; |
69 | 70 |
|
70 | 71 | /** Shared by {@link ReactScrollView} and {@link ReactHorizontalScrollView}. */ |
71 | | - public static void emitScrollEvent(ViewGroup scrollView, float xVelocity, float yVelocity) { |
| 72 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent( |
| 73 | + T scrollView, float xVelocity, float yVelocity) { |
72 | 74 | emitScrollEvent(scrollView, ScrollEventType.SCROLL, xVelocity, yVelocity); |
73 | 75 | } |
74 | 76 |
|
75 | | - public static void emitScrollBeginDragEvent(ViewGroup scrollView) { |
| 77 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollBeginDragEvent( |
| 78 | + T scrollView) { |
76 | 79 | emitScrollEvent(scrollView, ScrollEventType.BEGIN_DRAG); |
77 | 80 | } |
78 | 81 |
|
79 | | - public static void emitScrollEndDragEvent( |
80 | | - ViewGroup scrollView, float xVelocity, float yVelocity) { |
| 82 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEndDragEvent( |
| 83 | + T scrollView, float xVelocity, float yVelocity) { |
81 | 84 | emitScrollEvent(scrollView, ScrollEventType.END_DRAG, xVelocity, yVelocity); |
82 | 85 | } |
83 | 86 |
|
84 | | - public static void emitScrollMomentumBeginEvent( |
85 | | - ViewGroup scrollView, int xVelocity, int yVelocity) { |
| 87 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollMomentumBeginEvent( |
| 88 | + T scrollView, int xVelocity, int yVelocity) { |
86 | 89 | emitScrollEvent(scrollView, ScrollEventType.MOMENTUM_BEGIN, xVelocity, yVelocity); |
87 | 90 | } |
88 | 91 |
|
89 | | - public static void emitScrollMomentumEndEvent(ViewGroup scrollView) { |
| 92 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollMomentumEndEvent( |
| 93 | + T scrollView) { |
90 | 94 | emitScrollEvent(scrollView, ScrollEventType.MOMENTUM_END); |
91 | 95 | } |
92 | 96 |
|
93 | | - private static void emitScrollEvent(ViewGroup scrollView, ScrollEventType scrollEventType) { |
| 97 | + private static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent( |
| 98 | + T scrollView, ScrollEventType scrollEventType) { |
94 | 99 | emitScrollEvent(scrollView, scrollEventType, 0, 0); |
95 | 100 | } |
96 | 101 |
|
97 | | - private static void emitScrollEvent( |
98 | | - ViewGroup scrollView, ScrollEventType scrollEventType, float xVelocity, float yVelocity) { |
| 102 | + private static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent( |
| 103 | + T scrollView, ScrollEventType scrollEventType, float xVelocity, float yVelocity) { |
| 104 | + long now = System.currentTimeMillis(); |
| 105 | + // Throttle the scroll event if scrollEventThrottle is set to be equal or more than 17 ms. |
| 106 | + // We limit the delta to 17ms so that small throttles intended to enable 60fps updates will not |
| 107 | + // inadvertently filter out any scroll events. |
| 108 | + if (ReactFeatureFlags.enableScrollEventThrottle |
| 109 | + && scrollView.getScrollEventThrottle() |
| 110 | + >= Math.max(17, now - scrollView.getLastScrollDispatchTime())) { |
| 111 | + // Scroll events are throttled. |
| 112 | + return; |
| 113 | + } |
| 114 | + |
99 | 115 | View contentView = scrollView.getChildAt(0); |
100 | 116 |
|
101 | 117 | if (contentView == null) { |
@@ -129,6 +145,7 @@ private static void emitScrollEvent( |
129 | 145 | contentView.getHeight(), |
130 | 146 | scrollView.getWidth(), |
131 | 147 | scrollView.getHeight())); |
| 148 | + scrollView.setLastScrollDispatchTime(now); |
132 | 149 | } |
133 | 150 | } |
134 | 151 |
|
@@ -469,7 +486,7 @@ public WritableMap getStateUpdate() { |
469 | 486 | public static < |
470 | 487 | T extends |
471 | 488 | ViewGroup & FabricViewStateManager.HasFabricViewStateManager & HasScrollState |
472 | | - & HasFlingAnimator> |
| 489 | + & HasFlingAnimator & HasScrollEventThrottle> |
473 | 490 | void updateStateOnScrollChanged( |
474 | 491 | final T scrollView, final float xVelocity, final float yVelocity) { |
475 | 492 | // Race an UpdateState with every onScroll. This makes it more likely that, in Fabric, |
@@ -579,4 +596,21 @@ public interface HasFlingAnimator { |
579 | 596 | /** Get the fling distance with current velocity for prediction */ |
580 | 597 | int getFlingExtrapolatedDistance(int velocity); |
581 | 598 | } |
| 599 | + |
| 600 | + public interface HasScrollEventThrottle { |
| 601 | + /** |
| 602 | + * Set the scroll event throttle in ms. This number is used to throttle the scroll events. The |
| 603 | + * default value is zero, which means the scroll events are sent with no throttle. |
| 604 | + */ |
| 605 | + void setScrollEventThrottle(int scrollEventThrottle); |
| 606 | + |
| 607 | + /** Get the scroll event throttle in ms. */ |
| 608 | + int getScrollEventThrottle(); |
| 609 | + |
| 610 | + /** Set the scroll view's last dispatch time for throttling */ |
| 611 | + void setLastScrollDispatchTime(long lastScrollDispatchTime); |
| 612 | + |
| 613 | + /** Get the scroll view dispatch time for throttling */ |
| 614 | + long getLastScrollDispatchTime(); |
| 615 | + } |
582 | 616 | } |
0 commit comments