move ReactInstanceManager.Builder out of ReactInstanceManager into it's own class ReactInstanceManagerBuilder

Reviewed By: thechefchen

Differential Revision: D4451541

fbshipit-source-id: d9cbcb61b232e817a1f4ff7b067a8a4e0c17150a
This commit is contained in:
Aaron Chiu 2017-01-23 17:00:17 -08:00 committed by Facebook Github Bot
parent f9df72c803
commit 17c9939444
6 changed files with 245 additions and 228 deletions

View File

@ -22,6 +22,7 @@ import android.widget.FrameLayout;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactInstanceManagerBuilder;
import com.facebook.react.ReactRootView; import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.common.LifecycleState; import com.facebook.react.common.LifecycleState;
@ -149,7 +150,7 @@ public class ReactAppTestActivity extends FragmentActivity implements
final CountDownLatch currentLayoutEvent = mLayoutEvent = new CountDownLatch(1); final CountDownLatch currentLayoutEvent = mLayoutEvent = new CountDownLatch(1);
mBridgeIdleSignaler = new ReactBridgeIdleSignaler(); mBridgeIdleSignaler = new ReactBridgeIdleSignaler();
ReactInstanceManager.Builder builder = ReactInstanceManagerBuilder builder =
ReactTestHelper.getReactTestFactory().getReactInstanceManagerBuilder() ReactTestHelper.getReactTestFactory().getReactInstanceManagerBuilder()
.setApplication(getApplication()) .setApplication(getApplication())
.setBundleAssetName(bundleName) .setBundleAssetName(bundleName)

View File

@ -10,7 +10,7 @@ package com.facebook.react.testing;
import android.content.Context; import android.content.Context;
import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactInstanceManagerBuilder;
import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.NativeModule;
@ -23,5 +23,5 @@ public interface ReactTestFactory {
} }
ReactInstanceEasyBuilder getCatalystInstanceBuilder(); ReactInstanceEasyBuilder getCatalystInstanceBuilder();
ReactInstanceManager.Builder getReactInstanceManagerBuilder(); ReactInstanceManagerBuilder getReactInstanceManagerBuilder();
} }

View File

@ -22,6 +22,7 @@ import android.view.ViewGroup;
import com.facebook.react.EagerModuleProvider; import com.facebook.react.EagerModuleProvider;
import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactInstanceManagerBuilder;
import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.JavaScriptModuleRegistry; import com.facebook.react.bridge.JavaScriptModuleRegistry;
import com.facebook.react.bridge.ModuleSpec; import com.facebook.react.bridge.ModuleSpec;
@ -103,7 +104,7 @@ public class ReactTestHelper {
} }
@Override @Override
public ReactInstanceManager.Builder getReactInstanceManagerBuilder() { public ReactInstanceManagerBuilder getReactInstanceManagerBuilder() {
return ReactInstanceManager.builder(); return ReactInstanceManager.builder();
} }
} }

View File

@ -11,25 +11,17 @@ package com.facebook.react;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import android.app.Activity; import android.app.Activity;
import android.app.Application;
import android.content.Intent; import android.content.Intent;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.NativeModuleCallExceptionHandler;
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.common.LifecycleState; import com.facebook.react.common.LifecycleState;
import com.facebook.react.cxxbridge.JSBundleLoader; import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.devsupport.DevSupportManager; import com.facebook.react.devsupport.DevSupportManager;
import com.facebook.react.devsupport.RedBoxHandler;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.uimanager.UIImplementationProvider;
import com.facebook.react.uimanager.ViewManager; import com.facebook.react.uimanager.ViewManager;
/** /**
@ -200,219 +192,7 @@ public abstract class ReactInstanceManager {
/** /**
* Creates a builder that is capable of creating an instance of {@link ReactInstanceManagerImpl}. * Creates a builder that is capable of creating an instance of {@link ReactInstanceManagerImpl}.
*/ */
public static Builder builder() { public static ReactInstanceManagerBuilder builder() {
return new Builder(); return new ReactInstanceManagerBuilder();
}
/**
* Builder class for {@link ReactInstanceManagerImpl}
*/
public static class Builder {
protected final List<ReactPackage> mPackages = new ArrayList<>();
protected @Nullable String mJSBundleAssetUrl;
protected @Nullable JSBundleLoader mJSBundleLoader;
protected @Nullable String mJSMainModuleName;
protected @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
protected @Nullable Application mApplication;
protected boolean mUseDeveloperSupport;
protected @Nullable LifecycleState mInitialLifecycleState;
protected @Nullable UIImplementationProvider mUIImplementationProvider;
protected @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
protected JSCConfig mJSCConfig = JSCConfig.EMPTY;
protected @Nullable Activity mCurrentActivity;
protected @Nullable DefaultHardwareBackBtnHandler mDefaultHardwareBackBtnHandler;
protected @Nullable RedBoxHandler mRedBoxHandler;
protected boolean mLazyNativeModulesEnabled;
protected boolean mLazyViewManagersEnabled;
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) {
mJSBundleAssetUrl = (bundleAssetName == null ? null : "assets://" + bundleAssetName);
mJSBundleLoader = null;
return this;
}
/**
* Path to the JS bundle file to be loaded from the file system.
*
* Example: {@code "assets://index.android.js" or "/sdcard/main.jsbundle"}
*/
public Builder setJSBundleFile(String jsBundleFile) {
if (jsBundleFile.startsWith("assets://")) {
mJSBundleAssetUrl = jsBundleFile;
mJSBundleLoader = null;
return this;
}
return setJSBundleLoader(JSBundleLoader.createFileLoader(jsBundleFile));
}
/**
* Bundle loader to use when setting up JS environment. This supersedes
* prior invcations of {@link setJSBundleFile} and {@link setBundleAssetName}.
*
* Example: {@code JSBundleLoader.createFileLoader(application, bundleFile)}
*/
public Builder setJSBundleLoader(JSBundleLoader jsBundleLoader) {
mJSBundleLoader = jsBundleLoader;
mJSBundleAssetUrl = null;
return this;
}
/**
* Path to your app's main module on the packager server. This is used when
* reloading JS during development. All paths are relative to the root folder
* the packager is serving files from.
* Examples:
* {@code "index.android"} or
* {@code "subdirectory/index.android"}
*/
public Builder setJSMainModuleName(String jsMainModuleName) {
mJSMainModuleName = jsMainModuleName;
return this;
}
public Builder addPackage(ReactPackage reactPackage) {
mPackages.add(reactPackage);
return this;
}
public Builder setBridgeIdleDebugListener(
NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener) {
mBridgeIdleDebugListener = bridgeIdleDebugListener;
return this;
}
/**
* Required. This must be your {@code Application} instance.
*/
public Builder setApplication(Application application) {
mApplication = application;
return this;
}
public Builder setCurrentActivity(Activity activity) {
mCurrentActivity = activity;
return this;
}
public Builder setDefaultHardwareBackBtnHandler(
DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler) {
mDefaultHardwareBackBtnHandler = defaultHardwareBackBtnHandler;
return this;
}
/**
* When {@code true}, developer options such as JS reloading and debugging are enabled.
* Note you still have to call {@link #showDevOptionsDialog} to show the dev menu,
* e.g. when the device Menu button is pressed.
*/
public Builder setUseDeveloperSupport(boolean useDeveloperSupport) {
mUseDeveloperSupport = useDeveloperSupport;
return this;
}
/**
* Sets the initial lifecycle state of the host. For example, if the host is already resumed at
* creation time, we wouldn't expect an onResume call until we get an onPause call.
*/
public Builder setInitialLifecycleState(LifecycleState initialLifecycleState) {
mInitialLifecycleState = initialLifecycleState;
return this;
}
/**
* Set the exception handler for all native module calls. If not set, the default
* {@link DevSupportManager} will be used, which shows a redbox in dev mode and rethrows
* (crashes the app) in prod mode.
*/
public Builder setNativeModuleCallExceptionHandler(NativeModuleCallExceptionHandler handler) {
mNativeModuleCallExceptionHandler = handler;
return this;
}
public Builder setJSCConfig(JSCConfig jscConfig) {
mJSCConfig = jscConfig;
return this;
}
public Builder setRedBoxHandler(@Nullable RedBoxHandler redBoxHandler) {
mRedBoxHandler = redBoxHandler;
return this;
}
public Builder setLazyNativeModulesEnabled(boolean lazyNativeModulesEnabled) {
mLazyNativeModulesEnabled = lazyNativeModulesEnabled;
return this;
}
public Builder setLazyViewManagersEnabled(boolean lazyViewManagersEnabled) {
mLazyViewManagersEnabled = lazyViewManagersEnabled;
return this;
}
/**
* Instantiates a new {@link ReactInstanceManagerImpl}.
* Before calling {@code build}, the following must be called:
* <ul>
* <li> {@link #setApplication}
* <li> {@link #setCurrentActivity} if the activity has already resumed
* <li> {@link #setDefaultHardwareBackBtnHandler} if the activity has already resumed
* <li> {@link #setJSBundleFile} or {@link #setJSMainModuleName}
* </ul>
*/
public ReactInstanceManager build() {
Assertions.assertNotNull(
mApplication,
"Application property has not been set with this builder");
Assertions.assertCondition(
mUseDeveloperSupport || mJSBundleAssetUrl != null || mJSBundleLoader != null,
"JS Bundle File or Asset URL has to be provided when dev support is disabled");
Assertions.assertCondition(
mJSMainModuleName != null || mJSBundleAssetUrl != null || mJSBundleLoader != 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 XReactInstanceManagerImpl(
mApplication,
mCurrentActivity,
mDefaultHardwareBackBtnHandler,
(mJSBundleLoader == null && mJSBundleAssetUrl != null) ?
JSBundleLoader.createAssetLoader(mApplication, mJSBundleAssetUrl) : mJSBundleLoader,
mJSMainModuleName,
mPackages,
mUseDeveloperSupport,
mBridgeIdleDebugListener,
Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"),
mUIImplementationProvider,
mNativeModuleCallExceptionHandler,
mJSCConfig,
mRedBoxHandler,
mLazyNativeModulesEnabled,
mLazyViewManagersEnabled);
}
} }
} }

View File

@ -0,0 +1,235 @@
// Copyright 2004-present Facebook. All Rights Reserved.
package com.facebook.react;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.Application;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.NativeModuleCallExceptionHandler;
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.cxxbridge.JSBundleLoader;
import com.facebook.react.devsupport.DevSupportManager;
import com.facebook.react.devsupport.RedBoxHandler;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.uimanager.UIImplementationProvider;
/**
* Builder class for {@link ReactInstanceManager}
*/
public class ReactInstanceManagerBuilder {
protected final List<ReactPackage> mPackages = new ArrayList<>();
protected @Nullable String mJSBundleAssetUrl;
protected @Nullable JSBundleLoader mJSBundleLoader;
protected @Nullable String mJSMainModuleName;
protected @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
protected @Nullable Application mApplication;
protected boolean mUseDeveloperSupport;
protected @Nullable LifecycleState mInitialLifecycleState;
protected @Nullable UIImplementationProvider mUIImplementationProvider;
protected @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
protected JSCConfig mJSCConfig = JSCConfig.EMPTY;
protected @Nullable Activity mCurrentActivity;
protected @Nullable DefaultHardwareBackBtnHandler mDefaultHardwareBackBtnHandler;
protected @Nullable RedBoxHandler mRedBoxHandler;
protected boolean mLazyNativeModulesEnabled;
protected boolean mLazyViewManagersEnabled;
/* 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;
}
/**
* Name of the JS bundle file to be loaded from application's raw assets.
* Example: {@code "index.android.js"}
*/
public ReactInstanceManagerBuilder setBundleAssetName(String bundleAssetName) {
mJSBundleAssetUrl = (bundleAssetName == null ? null : "assets://" + bundleAssetName);
mJSBundleLoader = null;
return this;
}
/**
* Path to the JS bundle file to be loaded from the file system.
*
* Example: {@code "assets://index.android.js" or "/sdcard/main.jsbundle"}
*/
public ReactInstanceManagerBuilder setJSBundleFile(String jsBundleFile) {
if (jsBundleFile.startsWith("assets://")) {
mJSBundleAssetUrl = jsBundleFile;
mJSBundleLoader = null;
return this;
}
return setJSBundleLoader(JSBundleLoader.createFileLoader(jsBundleFile));
}
/**
* Bundle loader to use when setting up JS environment. This supersedes
* prior invcations of {@link setJSBundleFile} and {@link setBundleAssetName}.
*
* Example: {@code JSBundleLoader.createFileLoader(application, bundleFile)}
*/
public ReactInstanceManagerBuilder setJSBundleLoader(JSBundleLoader jsBundleLoader) {
mJSBundleLoader = jsBundleLoader;
mJSBundleAssetUrl = null;
return this;
}
/**
* Path to your app's main module on the packager server. This is used when
* reloading JS during development. All paths are relative to the root folder
* the packager is serving files from.
* Examples:
* {@code "index.android"} or
* {@code "subdirectory/index.android"}
*/
public ReactInstanceManagerBuilder setJSMainModuleName(String jsMainModuleName) {
mJSMainModuleName = jsMainModuleName;
return this;
}
public ReactInstanceManagerBuilder addPackage(ReactPackage reactPackage) {
mPackages.add(reactPackage);
return this;
}
public ReactInstanceManagerBuilder setBridgeIdleDebugListener(
NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener) {
mBridgeIdleDebugListener = bridgeIdleDebugListener;
return this;
}
/**
* Required. This must be your {@code Application} instance.
*/
public ReactInstanceManagerBuilder setApplication(Application application) {
mApplication = application;
return this;
}
public ReactInstanceManagerBuilder setCurrentActivity(Activity activity) {
mCurrentActivity = activity;
return this;
}
public ReactInstanceManagerBuilder setDefaultHardwareBackBtnHandler(
DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler) {
mDefaultHardwareBackBtnHandler = defaultHardwareBackBtnHandler;
return this;
}
/**
* When {@code true}, developer options such as JS reloading and debugging are enabled.
* Note you still have to call {@link #showDevOptionsDialog} to show the dev menu,
* e.g. when the device Menu button is pressed.
*/
public ReactInstanceManagerBuilder setUseDeveloperSupport(boolean useDeveloperSupport) {
mUseDeveloperSupport = useDeveloperSupport;
return this;
}
/**
* Sets the initial lifecycle state of the host. For example, if the host is already resumed at
* creation time, we wouldn't expect an onResume call until we get an onPause call.
*/
public ReactInstanceManagerBuilder setInitialLifecycleState(
LifecycleState initialLifecycleState) {
mInitialLifecycleState = initialLifecycleState;
return this;
}
/**
* Set the exception handler for all native module calls. If not set, the default
* {@link DevSupportManager} will be used, which shows a redbox in dev mode and rethrows
* (crashes the app) in prod mode.
*/
public ReactInstanceManagerBuilder setNativeModuleCallExceptionHandler(
NativeModuleCallExceptionHandler handler) {
mNativeModuleCallExceptionHandler = handler;
return this;
}
public ReactInstanceManagerBuilder setJSCConfig(JSCConfig jscConfig) {
mJSCConfig = jscConfig;
return this;
}
public ReactInstanceManagerBuilder setRedBoxHandler(@Nullable RedBoxHandler redBoxHandler) {
mRedBoxHandler = redBoxHandler;
return this;
}
public ReactInstanceManagerBuilder setLazyNativeModulesEnabled(boolean lazyNativeModulesEnabled) {
mLazyNativeModulesEnabled = lazyNativeModulesEnabled;
return this;
}
public ReactInstanceManagerBuilder setLazyViewManagersEnabled(boolean lazyViewManagersEnabled) {
mLazyViewManagersEnabled = lazyViewManagersEnabled;
return this;
}
/**
* Instantiates a new {@link ReactInstanceManagerImpl}.
* Before calling {@code build}, the following must be called:
* <ul>
* <li> {@link #setApplication}
* <li> {@link #setCurrentActivity} if the activity has already resumed
* <li> {@link #setDefaultHardwareBackBtnHandler} if the activity has already resumed
* <li> {@link #setJSBundleFile} or {@link #setJSMainModuleName}
* </ul>
*/
public ReactInstanceManager build() {
Assertions.assertNotNull(
mApplication,
"Application property has not been set with this builder");
Assertions.assertCondition(
mUseDeveloperSupport || mJSBundleAssetUrl != null || mJSBundleLoader != null,
"JS Bundle File or Asset URL has to be provided when dev support is disabled");
Assertions.assertCondition(
mJSMainModuleName != null || mJSBundleAssetUrl != null || mJSBundleLoader != 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 XReactInstanceManagerImpl(
mApplication,
mCurrentActivity,
mDefaultHardwareBackBtnHandler,
(mJSBundleLoader == null && mJSBundleAssetUrl != null) ?
JSBundleLoader.createAssetLoader(mApplication, mJSBundleAssetUrl) : mJSBundleLoader,
mJSMainModuleName,
mPackages,
mUseDeveloperSupport,
mBridgeIdleDebugListener,
Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"),
mUIImplementationProvider,
mNativeModuleCallExceptionHandler,
mJSCConfig,
mRedBoxHandler,
mLazyNativeModulesEnabled,
mLazyViewManagersEnabled);
}
}

View File

@ -63,7 +63,7 @@ public abstract class ReactNativeHost {
} }
protected ReactInstanceManager createReactInstanceManager() { protected ReactInstanceManager createReactInstanceManager() {
ReactInstanceManager.Builder builder = ReactInstanceManager.builder() ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
.setApplication(mApplication) .setApplication(mApplication)
.setJSMainModuleName(getJSMainModuleName()) .setJSMainModuleName(getJSMainModuleName())
.setUseDeveloperSupport(getUseDeveloperSupport()) .setUseDeveloperSupport(getUseDeveloperSupport())