From 3dca8cf9fdd864b1359fc7276bf98cb154c3e360 Mon Sep 17 00:00:00 2001 From: Denis Koroskin Date: Sun, 29 Nov 2015 22:24:36 -0800 Subject: [PATCH] Add UIImplementationProvider and allow overriding it in AbstractReactActivity Summary: public UIImplementationProvider allows plugging in an alternative UIImplementation. A follow up diff adds a toggle under FB Dev Settings and uses this class to control an implementation. This allows us experimenting with other ways of generating UI hierarchy from JavaScript components. Reviewed By: astreet Differential Revision: D2554774 fb-gh-sync-id: 6574a893020e3519bd2ab00b9620a6dbdfaed595 --- .../facebook/react/CoreModulesPackage.java | 11 ++++++--- .../facebook/react/ReactInstanceManager.java | 21 ++++++++++++++-- .../react/ReactInstanceManagerImpl.java | 8 +++++-- .../uimanager/UIImplementationProvider.java | 24 +++++++++++++++++++ .../react/uimanager/UIManagerModule.java | 9 ------- 5 files changed, 57 insertions(+), 16 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 5dd7b1959..b770b3b75 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java @@ -28,7 +28,7 @@ import com.facebook.react.modules.debug.SourceCodeModule; import com.facebook.react.modules.systeminfo.AndroidInfoModule; import com.facebook.react.uimanager.AppRegistry; import com.facebook.react.uimanager.ReactNative; -import com.facebook.react.uimanager.UIImplementation; +import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; import com.facebook.react.uimanager.debug.DebugComponentOwnershipModule; @@ -44,12 +44,15 @@ import com.facebook.systrace.Systrace; private final ReactInstanceManager mReactInstanceManager; private final DefaultHardwareBackBtnHandler mHardwareBackBtnHandler; + private final UIImplementationProvider mUIImplementationProvider; CoreModulesPackage( ReactInstanceManager reactInstanceManager, - DefaultHardwareBackBtnHandler hardwareBackBtnHandler) { + DefaultHardwareBackBtnHandler hardwareBackBtnHandler, + UIImplementationProvider uiImplementationProvider) { mReactInstanceManager = reactInstanceManager; mHardwareBackBtnHandler = hardwareBackBtnHandler; + mUIImplementationProvider = uiImplementationProvider; } @Override @@ -63,7 +66,9 @@ import com.facebook.systrace.Systrace; uiManagerModule = new UIManagerModule( catalystApplicationContext, viewManagersList, - new UIImplementation(catalystApplicationContext, viewManagersList)); + mUIImplementationProvider.createUIImplementation( + catalystApplicationContext, + viewManagersList)); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 609b320fc..2449c28ea 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -25,6 +25,7 @@ import com.facebook.react.bridge.ReactContext; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.devsupport.DevSupportManager; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; +import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.ViewManager; /** @@ -140,13 +141,23 @@ public abstract class ReactInstanceManager { protected @Nullable Application mApplication; protected boolean mUseDeveloperSupport; protected @Nullable LifecycleState mInitialLifecycleState; + protected @Nullable UIImplementationProvider mUIImplementationProvider; protected Builder() { } + /** + * Sets a provider of {@link UIImplementation}. + * Uses default provider if null is passed. + */ + public Builder setUIImplementationProvider( + @Nullable UIImplementationProvider uiImplementationProvider) { + mUIImplementationProvider = uiImplementationProvider; + return this; + } + /** * Name of the JS bundle file to be loaded from application's raw assets. - * * Example: {@code "index.android.js"} */ public Builder setBundleAssetName(String bundleAssetName) { @@ -231,6 +242,11 @@ public abstract class ReactInstanceManager { mJSMainModuleName != null || mJSBundleFile != null, "Either MainModuleName or JS Bundle File needs to be provided"); + if (mUIImplementationProvider == null) { + // create default UIImplementationProvider if the provided one is null. + mUIImplementationProvider = new UIImplementationProvider(); + } + return new ReactInstanceManagerImpl( Assertions.assertNotNull( mApplication, @@ -240,7 +256,8 @@ public abstract class ReactInstanceManager { mPackages, mUseDeveloperSupport, mBridgeIdleDebugListener, - Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set")); + Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"), + mUIImplementationProvider); } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java index deb6bf21c..c97a55b06 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java @@ -52,6 +52,7 @@ import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.uimanager.AppRegistry; import com.facebook.react.uimanager.ReactNative; +import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; import com.facebook.soloader.SoLoader; @@ -95,6 +96,7 @@ import com.facebook.systrace.Systrace; private String mSourceUrl; private @Nullable Activity mCurrentActivity; private volatile boolean mHasStartedCreatingInitialContext = false; + private final UIImplementationProvider mUIImplementationProvider; private final ReactInstanceDevCommandsHandler mDevInterface = new ReactInstanceDevCommandsHandler() { @@ -189,7 +191,8 @@ import com.facebook.systrace.Systrace; List packages, boolean useDeveloperSupport, @Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener, - LifecycleState initialLifecycleState) { + LifecycleState initialLifecycleState, + UIImplementationProvider uiImplementationProvider) { initializeSoLoaderIfNecessary(applicationContext); mApplicationContext = applicationContext; @@ -208,6 +211,7 @@ import com.facebook.systrace.Systrace; useDeveloperSupport); mBridgeIdleDebugListener = bridgeIdleDebugListener; mLifecycleState = initialLifecycleState; + mUIImplementationProvider = uiImplementationProvider; } @Override @@ -597,7 +601,7 @@ import com.facebook.systrace.Systrace; "createAndProcessCoreModulesPackage"); try { CoreModulesPackage coreModulesPackage = - new CoreModulesPackage(this, mBackBtnHandler); + new CoreModulesPackage(this, mBackBtnHandler, mUIImplementationProvider); processPackage(coreModulesPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); 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 000000000..3d1a4a2f3 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementationProvider.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +package com.facebook.react.uimanager; + +import java.util.List; + +import com.facebook.react.bridge.ReactApplicationContext; + +/** + * Provides UIImplementation to use in {@link UIManagerModule}. + */ +public class UIImplementationProvider { + public UIImplementation createUIImplementation( + ReactApplicationContext reactContext, + List viewManagers) { + return new UIImplementation(reactContext, viewManagers); + } +} 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 59fd688e3..b60598569 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -78,15 +78,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements private int mNextRootViewTag = 1; private int mBatchId = 0; - /** - * This contructor is temporarily here to workaround Sandcastle error. - */ - public UIManagerModule( - ReactApplicationContext reactContext, - List viewManagerList) { - this(reactContext, viewManagerList, new UIImplementation(reactContext, viewManagerList)); - } - public UIManagerModule( ReactApplicationContext reactContext, List viewManagerList,