mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Proposed fix for ScrollView race condition between C++ state update and onScroll
Summary: FlatList relies heavily on onScroll events + the measure API. In Fabric, usage of `measure` relies on C++ having an accurate view of the current scroll position of the ScrollView. We already have a mechanism for updating the scroll position in C++ using UpdateState. But, it is only used currently at the /beginning/ and /end/ of scrolling, and UpdateState is not called /during/ scrolling at all. This means that we will see a series of events like this while scrolling: ``` Scrolling begins UPDATE C++ STATE: scrollLeft = 0, scrollTop = 0 JS event: onScroll x=0, y=0 JS event: onScroll x=0, y=100 JS event: onScroll x=0, y=200 ... JS event: onScroll x=0, y=1000 UPDATE C++ STATE: scrollLeft = 0, scrollTop = 1000 ``` Notably, not many C++ state updates are queued; and the last one is queued AFTER the JS event is sent. The last JS event and UpdateState will race, which means that sometimes the C++ update will /lose/ and C++ will have an inaccurate view of the world when FlatList receives the onScroll event and calls `measure`. My proposed solution, gated behind a feature flag, is to delay /some/ onScroll events until the C++ UpdateState has made its way back to Java, and send UpdateStates more frequently. The balance here is that UpdateState is a relatively expensive operation, so we probably still want to call it /less/ than we call onScroll. This means that `measure` will still return some incorrect results but will return correct results more frequently. Win? Changelog: [Internal[ Reviewed By: mdvacca Differential Revision: D28558380 fbshipit-source-id: 11c7cd714fae67ee5a94c4413be988481413ec03
This commit is contained in:
committed by
Facebook GitHub Bot
parent
fa4045e4dd
commit
b161241db2
@@ -19,6 +19,11 @@ import com.facebook.proguard.annotations.DoNotStripAny;
|
||||
@DoNotStripAny
|
||||
public class ReactFeatureFlags {
|
||||
|
||||
/** An interface used to compute flags on demand. */
|
||||
public interface FlagProvider {
|
||||
boolean get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this application use TurboModules? If yes, then any module that inherits {@link
|
||||
* com.facebook.react.turbomodule.core.interfaces.TurboModule} will NOT be passed in to C++
|
||||
@@ -63,11 +68,6 @@ public class ReactFeatureFlags {
|
||||
/** Feature flag to configure eager initialization of MapBuffer So file */
|
||||
public static boolean enableEagerInitializeMapBufferSoFile = false;
|
||||
|
||||
/** An interface used to compute flags on demand. */
|
||||
public interface FlagProvider {
|
||||
boolean get();
|
||||
}
|
||||
|
||||
/** Should the RuntimeExecutor call JSIExecutor::flush()? */
|
||||
private static FlagProvider enableRuntimeExecutorFlushingProvider = null;
|
||||
|
||||
@@ -96,4 +96,17 @@ public class ReactFeatureFlags {
|
||||
|
||||
/** Enables Fabric for LogBox */
|
||||
public static boolean enableFabricInLogBox = false;
|
||||
|
||||
//
|
||||
// ScrollView C++ UpdateState vs onScroll race fixes
|
||||
//
|
||||
|
||||
/* Enables a "state race condition fix" for ScrollViews StateUpdate + onScroll event emitter */
|
||||
public static boolean enableScrollViewStateEventRaceFix = false;
|
||||
|
||||
/* Enables another "state race condition fix" for ScrollViews StateUpdate + onScroll event emitter. Races a StateUpdate with every onScroll event. */
|
||||
public static boolean enableScrollViewStateEventAlwaysRace = false;
|
||||
|
||||
/* Configure a min scroll delta for UpdateState to be called while still actively scrolling. */
|
||||
public static int scrollViewUpdateStateMinScrollDelta = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user