From 667ca15893f4ef0538ed34dd93a2c04696e01240 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Fri, 6 Apr 2018 17:16:55 -0700 Subject: [PATCH] android: don't process touch events too early Summary: There can be a race when loading JS from rootview for the first time vs touching rootview before JS is ready. This may cause redbox on the JS side. Reviewed By: mdvacca Differential Revision: D7531334 fbshipit-source-id: 36ffa1e5ff205f60b95e0a1d1016301ea76936aa --- .../com/facebook/react/ReactRootView.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 5b8e3c539..c1d74a4ae 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -84,7 +84,7 @@ public class ReactRootView extends SizeMonitoringFrameLayout private int mRootViewTag; private boolean mIsAttachedToInstance; private boolean mShouldLogContentAppeared; - private final JSTouchDispatcher mJSTouchDispatcher = new JSTouchDispatcher(this); + private @Nullable JSTouchDispatcher mJSTouchDispatcher; private final ReactAndroidHWInputDeviceHelper mAndroidHWInputDeviceHelper = new ReactAndroidHWInputDeviceHelper(this); private boolean mWasMeasured = false; private int mWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); @@ -183,6 +183,12 @@ public class ReactRootView extends SizeMonitoringFrameLayout "Unable to dispatch touch to JS as the catalyst instance has not been attached"); return; } + if (mJSTouchDispatcher == null) { + FLog.w( + ReactConstants.TAG, + "Unable to dispatch touch to JS before the dispatcher is available"); + return; + } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class) .getEventDispatcher(); @@ -264,6 +270,12 @@ public class ReactRootView extends SizeMonitoringFrameLayout "Unable to dispatch touch to JS as the catalyst instance has not been attached"); return; } + if (mJSTouchDispatcher == null) { + FLog.w( + ReactConstants.TAG, + "Unable to dispatch touch to JS before the dispatcher is available"); + return; + } ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class) .getEventDispatcher(); @@ -414,6 +426,11 @@ public class ReactRootView extends SizeMonitoringFrameLayout } public void onAttachedToReactInstance() { + // Create the touch dispatcher here instead of having it always available, to make sure + // that all touch events are only passed to JS after React/JS side is ready to consume + // them. Otherwise, these events might break the states expected by JS. + // Note that this callback was invoked from within the UI thread. + mJSTouchDispatcher = new JSTouchDispatcher(this); if (mRootViewEventListener != null) { mRootViewEventListener.onAttachedToReactInstance(this); } @@ -582,7 +599,7 @@ public class ReactRootView extends SizeMonitoringFrameLayout public ReactInstanceManager getReactInstanceManager() { return mReactInstanceManager; } - + /* package */ void sendEvent(String eventName, @Nullable WritableMap params) { if (mReactInstanceManager != null) { mReactInstanceManager.getCurrentReactContext()