From b002df945b267c6e36aa1041397ffd1c73167037 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Sat, 20 Oct 2018 11:24:55 -0700 Subject: [PATCH] Re-introduce UIImplementationProvider Summary: UIImplementationProvider was removed as part of D8650376, this was a breaking change that caused problems in OSS. This diff introduces the concept of a deprecated UIImplementationProvider again to allow OSS community to upgrade to latest version of RN. Reviewed By: achen1 Differential Revision: D10456317 fbshipit-source-id: 6817629524f927dfcb5ebc054dbfd983877b7606 --- .../facebook/react/CoreModulesPackage.java | 2 + .../facebook/react/ReactInstanceManager.java | 3 ++ .../react/ReactInstanceManagerBuilder.java | 18 ++++++++ .../com/facebook/react/ReactNativeHost.java | 12 ++++++ .../uimanager/UIImplementationProvider.java | 42 +++++++++++++++++++ .../react/uimanager/UIManagerModule.java | 35 ++++++++++++++-- 6 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java b/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java index d28f94aba04960..10260537294830 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java @@ -26,6 +26,7 @@ import com.facebook.react.modules.debug.SourceCodeModule; import com.facebook.react.modules.deviceinfo.DeviceInfoModule; import com.facebook.react.modules.systeminfo.AndroidInfoModule; +import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; import com.facebook.systrace.Systrace; @@ -59,6 +60,7 @@ CoreModulesPackage( ReactInstanceManager reactInstanceManager, DefaultHardwareBackBtnHandler hardwareBackBtnHandler, + @Nullable UIImplementationProvider uiImplementationProvider, boolean lazyViewManagersEnabled, int minTimeLeftInFrameForNonBatchedOperationMs) { mReactInstanceManager = reactInstanceManager; diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index cf16006567187f..003311483f3219 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -81,6 +81,7 @@ import com.facebook.react.modules.fabric.ReactFabric; import com.facebook.react.packagerconnection.RequestHandler; import com.facebook.react.uimanager.DisplayMetricsHolder; +import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; @@ -200,6 +201,7 @@ public static ReactInstanceManagerBuilder builder() { boolean useDeveloperSupport, @Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener, LifecycleState initialLifecycleState, + @Nullable UIImplementationProvider mUIImplementationProvider, NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler, @Nullable RedBoxHandler redBoxHandler, boolean lazyViewManagersEnabled, @@ -250,6 +252,7 @@ public void invokeDefaultOnBackPressed() { ReactInstanceManager.this.invokeDefaultOnBackPressed(); } }, + mUIImplementationProvider, lazyViewManagersEnabled, minTimeLeftInFrameForNonBatchedOperationMs)); if (mUseDeveloperSupport) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java index 9c458612ad3dd9..00f3bb5d00373b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java @@ -22,6 +22,7 @@ import com.facebook.react.jscexecutor.JSCExecutorFactory; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.packagerconnection.RequestHandler; +import com.facebook.react.uimanager.UIImplementationProvider; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -41,6 +42,7 @@ public class ReactInstanceManagerBuilder { private @Nullable Application mApplication; private boolean mUseDeveloperSupport; private @Nullable LifecycleState mInitialLifecycleState; + private @Nullable UIImplementationProvider mUIImplementationProvider; private @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; private @Nullable Activity mCurrentActivity; private @Nullable DefaultHardwareBackBtnHandler mDefaultHardwareBackBtnHandler; @@ -56,6 +58,16 @@ public class ReactInstanceManagerBuilder { /* package protected */ ReactInstanceManagerBuilder() { } + /** + * Sets a provider of {@link UIImplementation}. + * Uses default provider if null is passed. + */ + public ReactInstanceManagerBuilder setUIImplementationProvider( + @Nullable UIImplementationProvider uiImplementationProvider) { + mUIImplementationProvider = uiImplementationProvider; + return this; + } + public ReactInstanceManagerBuilder setJSIModulesPackage( @Nullable JSIModulePackage jsiModulePackage) { mJSIModulesPackage = jsiModulePackage; @@ -242,6 +254,11 @@ public ReactInstanceManager build() { mJSMainModulePath != null || mJSBundleAssetUrl != null || mJSBundleLoader != null, "Either MainModulePath or JS Bundle File needs to be provided"); + if (mUIImplementationProvider == null) { + // create default UIImplementationProvider if the provided one is null. + mUIImplementationProvider = new UIImplementationProvider(); + } + // We use the name of the device and the app for debugging & metrics String appName = mApplication.getPackageName(); String deviceName = getFriendlyDeviceName(); @@ -262,6 +279,7 @@ public ReactInstanceManager build() { mUseDeveloperSupport, mBridgeIdleDebugListener, Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"), + mUIImplementationProvider, mNativeModuleCallExceptionHandler, mRedBoxHandler, mLazyViewManagersEnabled, diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java index f4e2d1fe933db5..d15abba7f760e1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java @@ -15,6 +15,7 @@ import com.facebook.react.bridge.ReactMarkerConstants; import com.facebook.react.common.LifecycleState; import com.facebook.react.devsupport.RedBoxHandler; +import com.facebook.react.uimanager.UIImplementationProvider; import java.util.List; import javax.annotation.Nullable; @@ -70,6 +71,7 @@ protected ReactInstanceManager createReactInstanceManager() { .setUseDeveloperSupport(getUseDeveloperSupport()) .setRedBoxHandler(getRedBoxHandler()) .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory()) + .setUIImplementationProvider(getUIImplementationProvider()) .setJSIModulesPackage(getJSIModulePackage()) .setInitialLifecycleState(LifecycleState.BEFORE_CREATE); @@ -107,6 +109,16 @@ protected final Application getApplication() { return mApplication; } + /** + * Get the {@link UIImplementationProvider} to use. Override this method if you want to use a + * custom UI implementation. + * + * Note: this is very advanced functionality, in 99% of cases you don't need to override this. + */ + protected UIImplementationProvider getUIImplementationProvider() { + return new UIImplementationProvider(); + } + protected @Nullable JSIModulePackage getJSIModulePackage() { return null; diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java new file mode 100644 index 00000000000000..379bf971619ce7 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +package com.facebook.react.uimanager; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.events.EventDispatcher; +import java.util.List; + +/** + * Provides UIImplementation to use in {@link UIManagerModule}. + */ +@Deprecated +public class UIImplementationProvider { + + public UIImplementation createUIImplementation( + ReactApplicationContext reactContext, + UIManagerModule.ViewManagerResolver viewManagerResolver, + EventDispatcher eventDispatcher, + int minTimeLeftInFrameForNonBatchedOperationMs) { + return new UIImplementation( + reactContext, + viewManagerResolver, + eventDispatcher, + minTimeLeftInFrameForNonBatchedOperationMs); + } + + public UIImplementation createUIImplementation( + ReactApplicationContext reactContext, + List viewManagerList, + EventDispatcher eventDispatcher, + int minTimeLeftInFrameForNonBatchedOperationMs) { + return new UIImplementation( + reactContext, + viewManagerList, + eventDispatcher, + minTimeLeftInFrameForNonBatchedOperationMs); + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 6075cda134a378..e0fa9fcefc6be6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -116,21 +116,47 @@ public interface CustomEventNamesResolver { private final MemoryTrimCallback mMemoryTrimCallback = new MemoryTrimCallback(); private final List mListeners = new ArrayList<>(); private @Nullable Map mViewManagerConstantsCache; - volatile private int mViewManagerConstantsCacheSize; + private volatile int mViewManagerConstantsCacheSize; private int mBatchId = 0; + @SuppressWarnings("deprecated") public UIManagerModule( ReactApplicationContext reactContext, ViewManagerResolver viewManagerResolver, int minTimeLeftInFrameForNonBatchedOperationMs) { + this( + reactContext, + viewManagerResolver, + new UIImplementationProvider(), + minTimeLeftInFrameForNonBatchedOperationMs); + } + + @SuppressWarnings("deprecated") + public UIManagerModule( + ReactApplicationContext reactContext, + List viewManagersList, + int minTimeLeftInFrameForNonBatchedOperationMs) { + this( + reactContext, + viewManagersList, + new UIImplementationProvider(), + minTimeLeftInFrameForNonBatchedOperationMs); + } + + @Deprecated + public UIManagerModule( + ReactApplicationContext reactContext, + ViewManagerResolver viewManagerResolver, + UIImplementationProvider uiImplementationProvider, + int minTimeLeftInFrameForNonBatchedOperationMs) { super(reactContext); DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext); mEventDispatcher = new EventDispatcher(reactContext); mModuleConstants = createConstants(viewManagerResolver); mCustomDirectEvents = UIManagerModuleConstants.getDirectEventTypeConstants(); mUIImplementation = - new UIImplementation( + uiImplementationProvider.createUIImplementation( reactContext, viewManagerResolver, mEventDispatcher, @@ -139,9 +165,11 @@ public UIManagerModule( reactContext.addLifecycleEventListener(this); } + @Deprecated public UIManagerModule( ReactApplicationContext reactContext, List viewManagersList, + UIImplementationProvider uiImplementationProvider, int minTimeLeftInFrameForNonBatchedOperationMs) { super(reactContext); DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext); @@ -149,7 +177,7 @@ public UIManagerModule( mCustomDirectEvents = MapBuilder.newHashMap(); mModuleConstants = createConstants(viewManagersList, null, mCustomDirectEvents); mUIImplementation = - new UIImplementation( + uiImplementationProvider.createUIImplementation( reactContext, viewManagersList, mEventDispatcher, @@ -157,6 +185,7 @@ public UIManagerModule( reactContext.addLifecycleEventListener(this); } + /** * This method gives an access to the {@link UIImplementation} object that can be used to execute * operations on the view hierarchy.