mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-02-08 09:12:05 +08:00
565 lines
21 KiB
Java
565 lines
21 KiB
Java
/**
|
|
* 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;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import android.app.Application;
|
|
import android.content.Context;
|
|
import android.os.Bundle;
|
|
import android.view.View;
|
|
|
|
import com.facebook.common.logging.FLog;
|
|
import com.facebook.infer.annotation.Assertions;
|
|
import com.facebook.react.bridge.Arguments;
|
|
import com.facebook.react.bridge.CatalystInstance;
|
|
import com.facebook.react.bridge.JSBundleLoader;
|
|
import com.facebook.react.bridge.JSCJavaScriptExecutor;
|
|
import com.facebook.react.bridge.JavaScriptExecutor;
|
|
import com.facebook.react.bridge.JavaScriptModule;
|
|
import com.facebook.react.bridge.JavaScriptModulesConfig;
|
|
import com.facebook.react.bridge.NativeModule;
|
|
import com.facebook.react.bridge.NativeModuleRegistry;
|
|
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
|
|
import com.facebook.react.bridge.ProxyJavaScriptExecutor;
|
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
import com.facebook.react.bridge.ReactContext;
|
|
import com.facebook.react.bridge.UiThreadUtil;
|
|
import com.facebook.react.bridge.WritableMap;
|
|
import com.facebook.react.bridge.WritableNativeMap;
|
|
import com.facebook.react.bridge.queue.CatalystQueueConfigurationSpec;
|
|
import com.facebook.react.common.ReactConstants;
|
|
import com.facebook.react.common.annotations.VisibleForTesting;
|
|
import com.facebook.react.devsupport.DevSupportManager;
|
|
import com.facebook.react.devsupport.ReactInstanceDevCommandsHandler;
|
|
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.UIManagerModule;
|
|
import com.facebook.react.uimanager.ViewManager;
|
|
import com.facebook.soloader.SoLoader;
|
|
|
|
/**
|
|
* This class is managing instances of {@link CatalystInstance}. It expose a way to configure
|
|
* catalyst instance using {@link ReactPackage} and keeps track of the lifecycle of that
|
|
* instance. It also sets up connection between the instance and developers support functionality
|
|
* of the framework.
|
|
*
|
|
* An instance of this manager is required to start JS application in {@link ReactRootView} (see
|
|
* {@link ReactRootView#startReactApplication} for more info).
|
|
*
|
|
* The lifecycle of the instance of {@link ReactInstanceManager} should be bound to the activity
|
|
* that owns the {@link ReactRootView} that is used to render react application using this
|
|
* instance manager (see {@link ReactRootView#startReactApplication}). It's required to pass
|
|
* owning activity's lifecycle events to the instance manager (see {@link #onPause},
|
|
* {@link #onDestroy} and {@link #onResume}).
|
|
*
|
|
* To instantiate an instance of this class use {@link #builder}.
|
|
*/
|
|
public class ReactInstanceManager {
|
|
|
|
/* should only be accessed from main thread (UI thread) */
|
|
private final List<ReactRootView> mAttachedRootViews = new ArrayList<>();
|
|
private LifecycleState mLifecycleState;
|
|
|
|
/* accessed from any thread */
|
|
private final @Nullable String mBundleAssetName; /* name of JS bundle file in assets folder */
|
|
private final @Nullable String mJSMainModuleName; /* path to JS bundle root on packager server */
|
|
private final List<ReactPackage> mPackages;
|
|
private final DevSupportManager mDevSupportManager;
|
|
private final boolean mUseDeveloperSupport;
|
|
private final @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
|
|
private @Nullable volatile ReactContext mCurrentReactContext;
|
|
private final Context mApplicationContext;
|
|
private @Nullable DefaultHardwareBackBtnHandler mDefaultBackButtonImpl;
|
|
|
|
private final ReactInstanceDevCommandsHandler mDevInterface =
|
|
new ReactInstanceDevCommandsHandler() {
|
|
|
|
@Override
|
|
public void onReloadWithJSDebugger(ProxyJavaScriptExecutor proxyExecutor) {
|
|
ReactInstanceManager.this.onReloadWithJSDebugger(proxyExecutor);
|
|
}
|
|
|
|
@Override
|
|
public void onJSBundleLoadedFromServer() {
|
|
ReactInstanceManager.this.onJSBundleLoadedFromServer();
|
|
}
|
|
|
|
@Override
|
|
public void toggleElementInspector() {
|
|
ReactInstanceManager.this.toggleElementInspector();
|
|
}
|
|
};
|
|
|
|
private final DefaultHardwareBackBtnHandler mBackBtnHandler =
|
|
new DefaultHardwareBackBtnHandler() {
|
|
@Override
|
|
public void invokeDefaultOnBackPressed() {
|
|
ReactInstanceManager.this.invokeDefaultOnBackPressed();
|
|
}
|
|
};
|
|
|
|
private ReactInstanceManager(
|
|
Context applicationContext,
|
|
@Nullable String bundleAssetName,
|
|
@Nullable String jsMainModuleName,
|
|
List<ReactPackage> packages,
|
|
boolean useDeveloperSupport,
|
|
@Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
|
|
LifecycleState initialLifecycleState) {
|
|
initializeSoLoaderIfNecessary(applicationContext);
|
|
|
|
mApplicationContext = applicationContext;
|
|
mBundleAssetName = bundleAssetName;
|
|
mJSMainModuleName = jsMainModuleName;
|
|
mPackages = packages;
|
|
mUseDeveloperSupport = useDeveloperSupport;
|
|
// We need to instantiate DevSupportManager regardless to the useDeveloperSupport option,
|
|
// although will prevent dev support manager from displaying any options or dialogs by
|
|
// checking useDeveloperSupport option before calling setDevSupportEnabled on this manager
|
|
// TODO(6803830): Don't instantiate devsupport manager when useDeveloperSupport is false
|
|
mDevSupportManager = new DevSupportManager(
|
|
applicationContext,
|
|
mDevInterface,
|
|
mJSMainModuleName,
|
|
useDeveloperSupport);
|
|
mBridgeIdleDebugListener = bridgeIdleDebugListener;
|
|
mLifecycleState = initialLifecycleState;
|
|
}
|
|
|
|
public DevSupportManager getDevSupportManager() {
|
|
return mDevSupportManager;
|
|
}
|
|
|
|
/**
|
|
* Creates a builder that is capable of creating an instance of {@link ReactInstanceManager}.
|
|
*/
|
|
public static Builder builder() {
|
|
return new Builder();
|
|
}
|
|
|
|
private static void initializeSoLoaderIfNecessary(Context applicationContext) {
|
|
// Call SoLoader.initialize here, this is required for apps that does not use exopackage and
|
|
// does not use SoLoader for loading other native code except from the one used by React Native
|
|
// This way we don't need to require others to have additional initialization code and to
|
|
// subclass android.app.Application.
|
|
|
|
// Method SoLoader.init is idempotent, so if you wish to use native exopackage, just call
|
|
// SoLoader.init with appropriate args before initializing ReactInstanceManager
|
|
SoLoader.init(applicationContext, /* native exopackage */ false);
|
|
}
|
|
|
|
/**
|
|
* This method will give JS the opportunity to consume the back button event. If JS does not
|
|
* consume the event, mDefaultBackButtonImpl will be invoked at the end of the round trip
|
|
* to JS.
|
|
*/
|
|
public void onBackPressed() {
|
|
UiThreadUtil.assertOnUiThread();
|
|
ReactContext reactContext = mCurrentReactContext;
|
|
if (mCurrentReactContext == null) {
|
|
// Invoke without round trip to JS.
|
|
FLog.w(ReactConstants.TAG, "Instance detached from instance manager");
|
|
invokeDefaultOnBackPressed();
|
|
} else {
|
|
DeviceEventManagerModule deviceEventManagerModule =
|
|
Assertions.assertNotNull(reactContext).getNativeModule(DeviceEventManagerModule.class);
|
|
deviceEventManagerModule.emitHardwareBackPressed();
|
|
}
|
|
}
|
|
|
|
private void invokeDefaultOnBackPressed() {
|
|
UiThreadUtil.assertOnUiThread();
|
|
if (mDefaultBackButtonImpl != null) {
|
|
mDefaultBackButtonImpl.invokeDefaultOnBackPressed();
|
|
}
|
|
}
|
|
|
|
private void toggleElementInspector() {
|
|
if (mCurrentReactContext != null) {
|
|
mCurrentReactContext
|
|
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
.emit("toggleElementInspector", null);
|
|
}
|
|
}
|
|
|
|
public void onPause() {
|
|
UiThreadUtil.assertOnUiThread();
|
|
|
|
mLifecycleState = LifecycleState.BEFORE_RESUME;
|
|
|
|
mDefaultBackButtonImpl = null;
|
|
if (mUseDeveloperSupport) {
|
|
mDevSupportManager.setDevSupportEnabled(false);
|
|
}
|
|
|
|
if (mCurrentReactContext != null) {
|
|
mCurrentReactContext.onPause();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Use this method when the activity resumes to enable invoking the back button directly from JS.
|
|
*
|
|
* This method retains an instance to provided mDefaultBackButtonImpl. Thus it's
|
|
* important to pass from the activity instance that owns this particular instance of {@link
|
|
* ReactInstanceManager}, so that once this instance receive {@link #onDestroy} event it will
|
|
* clear the reference to that defaultBackButtonImpl.
|
|
*
|
|
* @param defaultBackButtonImpl a {@link DefaultHardwareBackBtnHandler} from an Activity that owns
|
|
* this instance of {@link ReactInstanceManager}.
|
|
*/
|
|
public void onResume(DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
|
|
UiThreadUtil.assertOnUiThread();
|
|
|
|
mLifecycleState = LifecycleState.RESUMED;
|
|
|
|
mDefaultBackButtonImpl = defaultBackButtonImpl;
|
|
if (mUseDeveloperSupport) {
|
|
mDevSupportManager.setDevSupportEnabled(true);
|
|
}
|
|
|
|
if (mCurrentReactContext != null) {
|
|
mCurrentReactContext.onResume();
|
|
}
|
|
}
|
|
|
|
public void onDestroy() {
|
|
UiThreadUtil.assertOnUiThread();
|
|
|
|
if (mUseDeveloperSupport) {
|
|
mDevSupportManager.setDevSupportEnabled(false);
|
|
}
|
|
|
|
if (mCurrentReactContext != null) {
|
|
mCurrentReactContext.onDestroy();
|
|
}
|
|
}
|
|
|
|
public void showDevOptionsDialog() {
|
|
UiThreadUtil.assertOnUiThread();
|
|
mDevSupportManager.showDevOptionsDialog();
|
|
}
|
|
|
|
/**
|
|
* Attach given {@param rootView} to a catalyst instance manager and start JS application using
|
|
* JS module provided by {@link ReactRootView#getJSModuleName}. This view will then be tracked
|
|
* by this manager and in case of catalyst instance restart it will be re-attached.
|
|
*/
|
|
/* package */ void attachMeasuredRootView(ReactRootView rootView) {
|
|
UiThreadUtil.assertOnUiThread();
|
|
mAttachedRootViews.add(rootView);
|
|
if (mCurrentReactContext == null) {
|
|
initializeReactContext();
|
|
} else {
|
|
attachMeasuredRootViewToInstance(rootView, mCurrentReactContext.getCatalystInstance());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Detach given {@param rootView} from current catalyst instance. It's safe to call this method
|
|
* multiple times on the same {@param rootView} - in that case view will be detached with the
|
|
* first call.
|
|
*/
|
|
/* package */ void detachRootView(ReactRootView rootView) {
|
|
UiThreadUtil.assertOnUiThread();
|
|
if (mAttachedRootViews.remove(rootView)) {
|
|
if (mCurrentReactContext != null && mCurrentReactContext.hasActiveCatalystInstance()) {
|
|
detachViewFromInstance(rootView, mCurrentReactContext.getCatalystInstance());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Uses configured {@link ReactPackage} instances to create all view managers
|
|
*/
|
|
/* package */ List<ViewManager> createAllViewManagers(
|
|
ReactApplicationContext catalystApplicationContext) {
|
|
List<ViewManager> allViewManagers = new ArrayList<>();
|
|
for (ReactPackage reactPackage : mPackages) {
|
|
allViewManagers.addAll(reactPackage.createViewManagers(catalystApplicationContext));
|
|
}
|
|
return allViewManagers;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public @Nullable ReactContext getCurrentReactContext() {
|
|
return mCurrentReactContext;
|
|
}
|
|
|
|
private void onReloadWithJSDebugger(ProxyJavaScriptExecutor proxyExecutor) {
|
|
recreateReactContext(
|
|
proxyExecutor,
|
|
JSBundleLoader.createRemoteDebuggerBundleLoader(
|
|
mDevSupportManager.getJSBundleURLForRemoteDebugging()));
|
|
}
|
|
|
|
private void onJSBundleLoadedFromServer() {
|
|
recreateReactContext(
|
|
new JSCJavaScriptExecutor(),
|
|
JSBundleLoader.createCachedBundleFromNetworkLoader(
|
|
mDevSupportManager.getSourceUrl(),
|
|
mDevSupportManager.getDownloadedJSBundleFile()));
|
|
}
|
|
|
|
private void initializeReactContext() {
|
|
if (mUseDeveloperSupport) {
|
|
if (mDevSupportManager.hasUpToDateJSBundleInCache()) {
|
|
// If there is a up-to-date bundle downloaded from server, always use that
|
|
onJSBundleLoadedFromServer();
|
|
return;
|
|
} else if (mBundleAssetName == null ||
|
|
!mDevSupportManager.hasBundleInAssets(mBundleAssetName)) {
|
|
// Bundle not available in assets, fetch from the server
|
|
mDevSupportManager.handleReloadJS();
|
|
return;
|
|
}
|
|
}
|
|
// Use JS file from assets
|
|
recreateReactContext(
|
|
new JSCJavaScriptExecutor(),
|
|
JSBundleLoader.createAssetLoader(
|
|
mApplicationContext.getAssets(),
|
|
mBundleAssetName));
|
|
}
|
|
|
|
private void recreateReactContext(
|
|
JavaScriptExecutor jsExecutor,
|
|
JSBundleLoader jsBundleLoader) {
|
|
UiThreadUtil.assertOnUiThread();
|
|
if (mCurrentReactContext != null) {
|
|
tearDownReactContext(mCurrentReactContext);
|
|
}
|
|
mCurrentReactContext = createReactContext(jsExecutor, jsBundleLoader);
|
|
for (ReactRootView rootView : mAttachedRootViews) {
|
|
attachMeasuredRootViewToInstance(
|
|
rootView,
|
|
mCurrentReactContext.getCatalystInstance());
|
|
}
|
|
}
|
|
|
|
private void attachMeasuredRootViewToInstance(
|
|
ReactRootView rootView,
|
|
CatalystInstance catalystInstance) {
|
|
UiThreadUtil.assertOnUiThread();
|
|
|
|
// Reset view content as it's going to be populated by the application content from JS
|
|
rootView.removeAllViews();
|
|
rootView.setId(View.NO_ID);
|
|
|
|
UIManagerModule uiManagerModule = catalystInstance.getNativeModule(UIManagerModule.class);
|
|
int rootTag = uiManagerModule.addMeasuredRootView(rootView);
|
|
@Nullable Bundle launchOptions = rootView.getLaunchOptions();
|
|
WritableMap initialProps = launchOptions != null
|
|
? Arguments.fromBundle(launchOptions)
|
|
: Arguments.createMap();
|
|
String jsAppModuleName = rootView.getJSModuleName();
|
|
|
|
WritableNativeMap appParams = new WritableNativeMap();
|
|
appParams.putDouble("rootTag", rootTag);
|
|
appParams.putMap("initialProps", initialProps);
|
|
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
|
|
}
|
|
|
|
private void detachViewFromInstance(
|
|
ReactRootView rootView,
|
|
CatalystInstance catalystInstance) {
|
|
UiThreadUtil.assertOnUiThread();
|
|
catalystInstance.getJSModule(ReactNative.class)
|
|
.unmountComponentAtNodeAndRemoveContainer(rootView.getId());
|
|
}
|
|
|
|
private void tearDownReactContext(ReactContext reactContext) {
|
|
UiThreadUtil.assertOnUiThread();
|
|
if (mLifecycleState == LifecycleState.RESUMED) {
|
|
reactContext.onPause();
|
|
}
|
|
for (ReactRootView rootView : mAttachedRootViews) {
|
|
detachViewFromInstance(rootView, reactContext.getCatalystInstance());
|
|
}
|
|
reactContext.onDestroy();
|
|
mDevSupportManager.onReactInstanceDestroyed(reactContext);
|
|
}
|
|
|
|
/**
|
|
* @return instance of {@link ReactContext} configured a {@link CatalystInstance} set
|
|
*/
|
|
private ReactApplicationContext createReactContext(
|
|
JavaScriptExecutor jsExecutor,
|
|
JSBundleLoader jsBundleLoader) {
|
|
NativeModuleRegistry.Builder nativeRegistryBuilder = new NativeModuleRegistry.Builder();
|
|
JavaScriptModulesConfig.Builder jsModulesBuilder = new JavaScriptModulesConfig.Builder();
|
|
|
|
ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
|
|
if (mUseDeveloperSupport) {
|
|
reactContext.setNativeModuleCallExceptionHandler(mDevSupportManager);
|
|
}
|
|
|
|
CoreModulesPackage coreModulesPackage =
|
|
new CoreModulesPackage(this, mBackBtnHandler);
|
|
processPackage(coreModulesPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder);
|
|
|
|
// TODO(6818138): Solve use-case of native/js modules overriding
|
|
for (ReactPackage reactPackage : mPackages) {
|
|
processPackage(reactPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder);
|
|
}
|
|
|
|
CatalystInstance.Builder catalystInstanceBuilder = new CatalystInstance.Builder()
|
|
.setCatalystQueueConfigurationSpec(CatalystQueueConfigurationSpec.createDefault())
|
|
.setJSExecutor(jsExecutor)
|
|
.setRegistry(nativeRegistryBuilder.build())
|
|
.setJSModulesConfig(jsModulesBuilder.build())
|
|
.setJSBundleLoader(jsBundleLoader)
|
|
.setNativeModuleCallExceptionHandler(mDevSupportManager);
|
|
|
|
CatalystInstance catalystInstance = catalystInstanceBuilder.build();
|
|
if (mBridgeIdleDebugListener != null) {
|
|
catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
|
|
}
|
|
|
|
reactContext.initializeWithInstance(catalystInstance);
|
|
catalystInstance.initialize();
|
|
mDevSupportManager.onNewReactContextCreated(reactContext);
|
|
|
|
moveReactContextToCurrentLifecycleState(reactContext);
|
|
|
|
return reactContext;
|
|
}
|
|
|
|
private void processPackage(
|
|
ReactPackage reactPackage,
|
|
ReactApplicationContext reactContext,
|
|
NativeModuleRegistry.Builder nativeRegistryBuilder,
|
|
JavaScriptModulesConfig.Builder jsModulesBuilder) {
|
|
for (NativeModule nativeModule : reactPackage.createNativeModules(reactContext)) {
|
|
nativeRegistryBuilder.add(nativeModule);
|
|
}
|
|
for (Class<? extends JavaScriptModule> jsModuleClass : reactPackage.createJSModules()) {
|
|
jsModulesBuilder.add(jsModuleClass);
|
|
}
|
|
}
|
|
|
|
private void moveReactContextToCurrentLifecycleState(ReactApplicationContext reactContext) {
|
|
if (mLifecycleState == LifecycleState.RESUMED) {
|
|
reactContext.onResume();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Builder class for {@link ReactInstanceManager}
|
|
*/
|
|
public static class Builder {
|
|
|
|
private final List<ReactPackage> mPackages = new ArrayList<>();
|
|
|
|
private @Nullable String mBundleAssetName;
|
|
private @Nullable String mJSMainModuleName;
|
|
private @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
|
|
private @Nullable Application mApplication;
|
|
private boolean mUseDeveloperSupport;
|
|
private @Nullable LifecycleState mInitialLifecycleState;
|
|
|
|
private Builder() {
|
|
}
|
|
|
|
/**
|
|
* Name of the JS budle file to be loaded from application's raw assets.
|
|
* Example: {@code "index.android.js"}
|
|
*/
|
|
public Builder setBundleAssetName(String bundleAssetName) {
|
|
mBundleAssetName = bundleAssetName;
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* Instantiates a new {@link ReactInstanceManager}.
|
|
* Before calling {@code build}, the following must be called:
|
|
* <ul>
|
|
* <li> {@link #setApplication}
|
|
* <li> {@link #setBundleAssetName} or {@link #setJSMainModuleName}
|
|
* </ul>
|
|
*/
|
|
public ReactInstanceManager build() {
|
|
Assertions.assertCondition(
|
|
mUseDeveloperSupport || mBundleAssetName != null,
|
|
"JS Bundle has to be provided in app assets when dev support is disabled");
|
|
Assertions.assertCondition(
|
|
mBundleAssetName != null || mJSMainModuleName != null,
|
|
"Either BundleAssetName or MainModuleName needs to be provided");
|
|
return new ReactInstanceManager(
|
|
Assertions.assertNotNull(
|
|
mApplication,
|
|
"Application property has not been set with this builder"),
|
|
mBundleAssetName,
|
|
mJSMainModuleName,
|
|
mPackages,
|
|
mUseDeveloperSupport,
|
|
mBridgeIdleDebugListener,
|
|
Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"));
|
|
}
|
|
}
|
|
}
|