PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react
Просмотр файла: ReactInstanceManager.java
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* 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;
import static com.facebook.infer.annotation.ThreadConfined.UI;
import static com.facebook.react.bridge.ReactMarkerConstants.ATTACH_MEASURED_ROOT_VIEWS_END;
import static com.facebook.react.bridge.ReactMarkerConstants.ATTACH_MEASURED_ROOT_VIEWS_START;
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_END;
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_START;
import static com.facebook.react.bridge.ReactMarkerConstants.CHANGE_THREAD_PRIORITY;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_START;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_REACT_CONTEXT_START;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_VIEW_MANAGERS_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_VIEW_MANAGERS_START;
import static com.facebook.react.bridge.ReactMarkerConstants.PRE_SETUP_REACT_CONTEXT_END;
import static com.facebook.react.bridge.ReactMarkerConstants.PRE_SETUP_REACT_CONTEXT_START;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_PACKAGES_END;
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_PACKAGES_START;
import static com.facebook.react.bridge.ReactMarkerConstants.REACT_CONTEXT_THREAD_END;
import static com.facebook.react.bridge.ReactMarkerConstants.REACT_CONTEXT_THREAD_START;
import static com.facebook.react.bridge.ReactMarkerConstants.SETUP_REACT_CONTEXT_END;
import static com.facebook.react.bridge.ReactMarkerConstants.SETUP_REACT_CONTEXT_START;
import static com.facebook.react.bridge.ReactMarkerConstants.VM_INIT;
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Process;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import com.facebook.common.logging.FLog;
import com.facebook.debug.holder.PrinterHolder;
import com.facebook.debug.tags.ReactDebugOverlayTags;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.ThreadConfined;
import com.facebook.infer.annotation.ThreadSafe;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.BridgeReactContext;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.CatalystInstanceImpl;
import com.facebook.react.bridge.JSBundleLoader;
import com.facebook.react.bridge.JSExceptionHandler;
import com.facebook.react.bridge.JavaScriptExecutor;
import com.facebook.react.bridge.JavaScriptExecutorFactory;
import com.facebook.react.bridge.NativeModuleRegistry;
import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactCxxErrorHandler;
import com.facebook.react.bridge.ReactInstanceManagerInspectorTarget;
import com.facebook.react.bridge.ReactMarker;
import com.facebook.react.bridge.ReactMarkerConstants;
import com.facebook.react.bridge.ReactNoCrashSoftException;
import com.facebook.react.bridge.ReactSoftExceptionLogger;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.bridge.UIManagerProvider;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.bridge.queue.ReactQueueConfigurationSpec;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.SurfaceDelegateFactory;
import com.facebook.react.common.annotations.internal.LegacyArchitecture;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogLevel;
import com.facebook.react.common.annotations.internal.LegacyArchitectureLogger;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.devsupport.DevSupportManagerFactory;
import com.facebook.react.devsupport.InspectorFlags;
import com.facebook.react.devsupport.ReactInstanceDevHelper;
import com.facebook.react.devsupport.inspector.InspectorNetworkHelper;
import com.facebook.react.devsupport.inspector.InspectorNetworkRequestListener;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
import com.facebook.react.devsupport.interfaces.DevLoadingViewManager;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.devsupport.interfaces.DevSupportManager.PausedInDebuggerOverlayCommandListener;
import com.facebook.react.devsupport.interfaces.PackagerStatusCallback;
import com.facebook.react.devsupport.interfaces.PausedInDebuggerOverlayManager;
import com.facebook.react.devsupport.interfaces.RedBoxHandler;
import com.facebook.react.interfaces.TaskInterface;
import com.facebook.react.internal.AndroidChoreographerProvider;
import com.facebook.react.internal.ChoreographerProvider;
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags;
import com.facebook.react.internal.turbomodule.core.TurboModuleManager;
import com.facebook.react.internal.turbomodule.core.TurboModuleManagerDelegate;
import com.facebook.react.modules.appearance.AppearanceModule;
import com.facebook.react.modules.appregistry.AppRegistry;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.modules.debug.interfaces.DeveloperSettings;
import com.facebook.react.modules.systeminfo.AndroidInfoHelpers;
import com.facebook.react.packagerconnection.RequestHandler;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.ReactRoot;
import com.facebook.react.uimanager.ReactStage;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.uimanager.common.UIManagerType;
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
import com.facebook.soloader.SoLoader;
import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This class is managing instances of {@link CatalystInstance}. It exposes 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.
*
* <p>An instance of this manager is required to start JS application in {@link ReactRootView} (see
* {@link ReactRootView#startReactApplication} for more info).
*
* <p>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 #onHostPause}, {@link
* #onHostDestroy} and {@link #onHostResume}).
*
* <p>To instantiate an instance of this class use {@link #builder}.
*/
@ThreadSafe
@LegacyArchitecture
public class ReactInstanceManager {
static {
LegacyArchitectureLogger.assertLegacyArchitecture(
"ReactInstanceManager", LegacyArchitectureLogLevel.WARNING);
}
private static final String TAG = ReactInstanceManager.class.getSimpleName();
/**
* Listener interface for react instance events. This class extends {@Link
* com.facebook.react.ReactInstanceEventListener} as a mitigation for both bridgeless and OSS
* compatibility: We create a separate ReactInstanceEventListener class to remove dependency on
* ReactInstanceManager which is a bridge-specific class, but in the mean time we have to keep
* ReactInstanceManager.ReactInstanceEventListener so OSS won't break.
*/
@Deprecated
public interface ReactInstanceEventListener
extends com.facebook.react.ReactInstanceEventListener {}
private final Set<ReactRoot> mAttachedReactRoots = Collections.synchronizedSet(new HashSet<>());
private volatile LifecycleState mLifecycleState;
private @Nullable @ThreadConfined(UI) ReactContextInitParams mPendingReactContextInitParams;
private volatile @Nullable Thread mCreateReactContextThread;
/* accessed from any thread */
private final JavaScriptExecutorFactory mJavaScriptExecutorFactory;
// See {@code ReactInstanceManagerBuilder} for description of all flags here.
private @Nullable Collection<String> mViewManagerNames = null;
private final @Nullable JSBundleLoader mBundleLoader;
private final @Nullable String mJSMainModulePath; /* path to JS bundle root on Metro */
private final List<ReactPackage> mPackages;
private final DevSupportManager mDevSupportManager;
private final boolean mUseDeveloperSupport;
private final boolean mRequireActivity;
private final boolean mKeepActivity;
private final @Nullable NotThreadSafeBridgeIdleDebugListener mBridgeIdleDebugListener;
private final Object mReactContextLock = new Object();
private @Nullable volatile ReactContext mCurrentReactContext;
private final Context mApplicationContext;
private @Nullable @ThreadConfined(UI) DefaultHardwareBackBtnHandler mDefaultBackButtonImpl;
private @Nullable Activity mCurrentActivity;
private @Nullable ReactInstanceManagerInspectorTarget mInspectorTarget;
private final Collection<com.facebook.react.ReactInstanceEventListener>
mReactInstanceEventListeners =
Collections.synchronizedList(
new ArrayList<com.facebook.react.ReactInstanceEventListener>());
// Identifies whether the instance manager is or soon will be initialized (on background thread)
private volatile boolean mHasStartedCreatingInitialContext = false;
// Identifies whether the instance manager destroy function is in process,
// while true any spawned create thread should wait for proper clean up before initializing
private volatile Boolean mHasStartedDestroying = false;
private final MemoryPressureRouter mMemoryPressureRouter;
private final @Nullable JSExceptionHandler mJSExceptionHandler;
private final @Nullable UIManagerProvider mUIManagerProvider;
private final @Nullable ReactPackageTurboModuleManagerDelegate.Builder mTMMDelegateBuilder;
private List<ViewManager> mViewManagers;
private boolean mUseFallbackBundle = true;
private volatile boolean mInstanceManagerInvalidated = false;
private class ReactContextInitParams {
private final JavaScriptExecutorFactory mJsExecutorFactory;
private final JSBundleLoader mJsBundleLoader;
public ReactContextInitParams(
JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {
mJsExecutorFactory = Assertions.assertNotNull(jsExecutorFactory);
mJsBundleLoader = Assertions.assertNotNull(jsBundleLoader);
}
public JavaScriptExecutorFactory getJsExecutorFactory() {
return mJsExecutorFactory;
}
public JSBundleLoader getJsBundleLoader() {
return mJsBundleLoader;
}
}
/** Creates a builder that is capable of creating an instance of {@link ReactInstanceManager}. */
public static ReactInstanceManagerBuilder builder() {
return new ReactInstanceManagerBuilder();
}
/* package */ ReactInstanceManager(
Context applicationContext,
@Nullable Activity currentActivity,
@Nullable DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler,
JavaScriptExecutorFactory javaScriptExecutorFactory,
@Nullable JSBundleLoader bundleLoader,
@Nullable String jsMainModulePath,
List<ReactPackage> packages,
boolean useDeveloperSupport,
DevSupportManagerFactory devSupportManagerFactory,
boolean requireActivity,
boolean keepActivity,
@Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
LifecycleState initialLifecycleState,
JSExceptionHandler jSExceptionHandler,
@Nullable RedBoxHandler redBoxHandler,
boolean lazyViewManagersEnabled,
@Nullable DevBundleDownloadListener devBundleDownloadListener,
int minNumShakes,
int minTimeLeftInFrameForNonBatchedOperationMs,
@Nullable UIManagerProvider uIManagerProvider,
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers,
@Nullable ReactPackageTurboModuleManagerDelegate.Builder tmmDelegateBuilder,
@Nullable SurfaceDelegateFactory surfaceDelegateFactory,
@Nullable DevLoadingViewManager devLoadingViewManager,
@Nullable ChoreographerProvider choreographerProvider,
@Nullable PausedInDebuggerOverlayManager pausedInDebuggerOverlayManager) {
FLog.d(TAG, "ReactInstanceManager.ctor()");
initializeSoLoaderIfNecessary(applicationContext);
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext);
// See {@code ReactInstanceManagerBuilder} for description of all flags here.
mApplicationContext = applicationContext;
mCurrentActivity = currentActivity;
mDefaultBackButtonImpl = defaultHardwareBackBtnHandler;
mJavaScriptExecutorFactory = javaScriptExecutorFactory;
mBundleLoader = bundleLoader;
mJSMainModulePath = jsMainModulePath;
mPackages = new ArrayList<>();
mUseDeveloperSupport = useDeveloperSupport;
mRequireActivity = requireActivity;
mKeepActivity = keepActivity;
Systrace.beginSection(TRACE_TAG_REACT, "ReactInstanceManager.initDevSupportManager");
mDevSupportManager =
devSupportManagerFactory.create(
applicationContext,
createDevHelperInterface(),
mJSMainModulePath,
useDeveloperSupport,
redBoxHandler,
devBundleDownloadListener,
minNumShakes,
customPackagerCommandHandlers,
surfaceDelegateFactory,
devLoadingViewManager,
pausedInDebuggerOverlayManager);
Systrace.endSection(TRACE_TAG_REACT);
mBridgeIdleDebugListener = bridgeIdleDebugListener;
mLifecycleState = initialLifecycleState;
mMemoryPressureRouter = new MemoryPressureRouter(applicationContext);
mJSExceptionHandler = jSExceptionHandler;
mTMMDelegateBuilder = tmmDelegateBuilder;
synchronized (mPackages) {
PrinterHolder.getPrinter()
.logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Use Split Packages");
mPackages.add(
new CoreModulesPackage(
this,
new DefaultHardwareBackBtnHandler() {
@Override
public void invokeDefaultOnBackPressed() {
ReactInstanceManager.this.invokeDefaultOnBackPressed();
}
},
lazyViewManagersEnabled,
minTimeLeftInFrameForNonBatchedOperationMs));
if (mUseDeveloperSupport) {
mPackages.add(new DebugCorePackage());
}
mPackages.addAll(packages);
}
mUIManagerProvider = uIManagerProvider;
// Instantiate ReactChoreographer in UI thread.
ReactChoreographer.initialize(
choreographerProvider != null
? choreographerProvider
: AndroidChoreographerProvider.getInstance());
if (mUseDeveloperSupport) {
mDevSupportManager.startInspector();
}
registerCxxErrorHandlerFunc();
}
private ReactInstanceDevHelper createDevHelperInterface() {
return new ReactInstanceDevHelper() {
@Override
public void onJSBundleLoadedFromServer() {
ReactInstanceManager.this.onJSBundleLoadedFromServer();
}
@Override
public void toggleElementInspector() {
ReactInstanceManager.this.toggleElementInspector();
}
@Override
public @Nullable Activity getCurrentActivity() {
return ReactInstanceManager.this.mCurrentActivity;
}
@Override
public JavaScriptExecutorFactory getJavaScriptExecutorFactory() {
return ReactInstanceManager.this.getJSExecutorFactory();
}
@Override
public @Nullable View createRootView(String appKey) {
Activity currentActivity = getCurrentActivity();
if (currentActivity != null) {
ReactRootView rootView = new ReactRootView(currentActivity);
boolean isFabric = ReactNativeNewArchitectureFeatureFlags.enableFabricRenderer();
rootView.setIsFabric(isFabric);
rootView.startReactApplication(ReactInstanceManager.this, appKey, new Bundle());
return rootView;
}
return null;
}
@Override
public void destroyRootView(View rootView) {
if (rootView instanceof ReactRootView) {
((ReactRootView) rootView).unmountReactApplication();
}
}
@Override
public void reload(String reason) {
// no-op not implemented for Bridge Mode
}
@Override
public TaskInterface<Boolean> loadBundle(JSBundleLoader bundleLoader) {
// no-op not implemented for Bridge Mode
return null;
}
@Override
public ReactContext getCurrentReactContext() {
// no-op not implemented for Bridge Mode
return null;
}
};
}
public synchronized void setUseFallbackBundle(boolean useFallbackBundle) {
mUseFallbackBundle = useFallbackBundle;
}
private JavaScriptExecutorFactory getJSExecutorFactory() {
return mJavaScriptExecutorFactory;
}
public DevSupportManager getDevSupportManager() {
return mDevSupportManager;
}
public MemoryPressureRouter getMemoryPressureRouter() {
return mMemoryPressureRouter;
}
public List<ReactPackage> getPackages() {
return new ArrayList<>(mPackages);
}
public void handleCxxError(Exception e) {
mDevSupportManager.handleException(e);
}
private void registerCxxErrorHandlerFunc() {
if (!ReactBuildConfig.UNSTABLE_ENABLE_MINIFY_LEGACY_ARCHITECTURE) {
Class[] parameterTypes = new Class[1];
parameterTypes[0] = Exception.class;
Method handleCxxErrorFunc = null;
try {
handleCxxErrorFunc = ReactInstanceManager.class.getMethod("handleCxxError", parameterTypes);
} catch (NoSuchMethodException e) {
FLog.e("ReactInstanceHolder", "Failed to set cxx error handler function", e);
}
ReactCxxErrorHandler.setHandleErrorFunc(this, handleCxxErrorFunc);
}
}
private void unregisterCxxErrorHandlerFunc() {
ReactCxxErrorHandler.setHandleErrorFunc(null, null);
}
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);
}
/**
* Trigger react context initialization asynchronously in a background async task. This enables
* applications to pre-load the application JS, and execute global code before {@link
* ReactRootView} is available and measured.
*
* <p>Called from UI thread.
*/
@ThreadConfined(UI)
public void createReactContextInBackground() {
FLog.d(TAG, "ReactInstanceManager.createReactContextInBackground()");
UiThreadUtil
.assertOnUiThread(); // Assert before setting mHasStartedCreatingInitialContext = true
if (!mHasStartedCreatingInitialContext) {
mHasStartedCreatingInitialContext = true;
recreateReactContextInBackgroundInner();
}
}
/**
* Recreate the react application and context. This should be called if configuration has changed
* or the developer has requested the app to be reloaded. It should only be called after an
* initial call to createReactContextInBackground.
*
* <p>Called from UI thread.
*/
@ThreadConfined(UI)
public void recreateReactContextInBackground() {
Assertions.assertCondition(
mHasStartedCreatingInitialContext,
"recreateReactContextInBackground should only be called after the initial "
+ "createReactContextInBackground call.");
recreateReactContextInBackgroundInner();
}
@ThreadConfined(UI)
private void recreateReactContextInBackgroundInner() {
FLog.d(TAG, "ReactInstanceManager.recreateReactContextInBackgroundInner()");
PrinterHolder.getPrinter()
.logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: recreateReactContextInBackground");
UiThreadUtil.assertOnUiThread();
if (mUseDeveloperSupport && mJSMainModulePath != null) {
final DeveloperSettings devSettings = mDevSupportManager.getDevSettings();
if (!Systrace.isTracing(TRACE_TAG_REACT)) {
if (mBundleLoader == null) {
mDevSupportManager.handleReloadJS();
} else {
mDevSupportManager.isPackagerRunning(
new PackagerStatusCallback() {
@Override
public void onPackagerStatusFetched(final boolean packagerIsRunning) {
UiThreadUtil.runOnUiThread(
() -> {
// ReactInstanceManager is no longer valid, ignore callback
if (mInstanceManagerInvalidated) {
return;
}
if (packagerIsRunning) {
mDevSupportManager.handleReloadJS();
} else if (mDevSupportManager.hasUpToDateJSBundleInCache()
&& !mUseFallbackBundle) {
// If there is a up-to-date bundle downloaded from server,
// with remote JS debugging disabled, always use that.
onJSBundleLoadedFromServer();
} else {
recreateReactContextInBackgroundFromBundleLoader();
}
});
}
});
}
return;
}
}
recreateReactContextInBackgroundFromBundleLoader();
}
@ThreadConfined(UI)
private void recreateReactContextInBackgroundFromBundleLoader() {
FLog.d(TAG, "ReactInstanceManager.recreateReactContextInBackgroundFromBundleLoader()");
PrinterHolder.getPrinter()
.logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from BundleLoader");
recreateReactContextInBackground(mJavaScriptExecutorFactory, mBundleLoader);
}
/**
* @return whether createReactContextInBackground has been called. Will return false after
* onDestroy until a new initial context has been created.
*/
public boolean hasStartedCreatingInitialContext() {
return mHasStartedCreatingInitialContext;
}
/**
* 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 (reactContext == null) {
// Invoke without round trip to JS.
FLog.w(TAG, "Instance detached from instance manager");
invokeDefaultOnBackPressed();
} else {
DeviceEventManagerModule deviceEventManagerModule =
reactContext.getNativeModule(DeviceEventManagerModule.class);
if (deviceEventManagerModule != null) {
deviceEventManagerModule.emitHardwareBackPressed();
}
}
}
private void invokeDefaultOnBackPressed() {
UiThreadUtil.assertOnUiThread();
if (mDefaultBackButtonImpl != null) {
mDefaultBackButtonImpl.invokeDefaultOnBackPressed();
}
}
/** This method will give JS the opportunity to receive intents via Linking. */
@ThreadConfined(UI)
public void onNewIntent(Intent intent) {
UiThreadUtil.assertOnUiThread();
ReactContext currentContext = getCurrentReactContext();
if (currentContext == null) {
FLog.w(TAG, "Instance detached from instance manager");
} else {
String action = intent.getAction();
Uri uri = intent.getData();
if (uri != null
&& (Intent.ACTION_VIEW.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))) {
DeviceEventManagerModule deviceEventManagerModule =
currentContext.getNativeModule(DeviceEventManagerModule.class);
if (deviceEventManagerModule != null) {
deviceEventManagerModule.emitNewIntentReceived(uri);
}
}
currentContext.onNewIntent(mCurrentActivity, intent);
}
}
private void toggleElementInspector() {
ReactContext currentContext = getCurrentReactContext();
if (currentContext != null && currentContext.hasActiveReactInstance()) {
currentContext.emitDeviceEvent("toggleElementInspector");
} else {
ReactSoftExceptionLogger.logSoftException(
TAG,
new ReactNoCrashSoftException(
"Cannot toggleElementInspector, CatalystInstance not available"));
}
}
/**
* Call this from {@link Activity#onPause()}. This notifies any listening modules so they can do
* any necessary cleanup.
*
* @deprecated Use {@link #onHostPause(Activity)} instead.
*/
@ThreadConfined(UI)
@Deprecated
public void onHostPause() {
UiThreadUtil.assertOnUiThread();
mDefaultBackButtonImpl = null;
if (mUseDeveloperSupport) {
mDevSupportManager.setDevSupportEnabled(false);
}
moveToBeforeResumeLifecycleState();
}
/**
* This method should be called from {@link Activity#onUserLeaveHint()}. It notifies all listening
* modules that the user is about to leave the activity. The passed Activity is has to be the
* current Activity.
*
* @param activity the activity being backgrounded as a result of user action
*/
@ThreadConfined(UI)
public void onUserLeaveHint(@Nullable Activity activity) {
if (mCurrentActivity != null && activity == mCurrentActivity) {
UiThreadUtil.assertOnUiThread();
ReactContext currentContext = getCurrentReactContext();
if (currentContext != null) {
currentContext.onUserLeaveHint(activity);
}
}
}
/**
* Call this from {@link Activity#onPause()}. This notifies any listening modules so they can do
* any necessary cleanup. The passed Activity is the current Activity being paused. This will
* always be the foreground activity that would be returned by {@link
* ReactContext#getCurrentActivity()}.
*
* @param activity the activity being paused
*/
@ThreadConfined(UI)
public void onHostPause(@Nullable Activity activity) {
if (mRequireActivity) {
if (mCurrentActivity == null) {
String message = "ReactInstanceManager.onHostPause called with null activity";
FLog.e(TAG, message);
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for (StackTraceElement element : stackTrace) {
FLog.e(TAG, element.toString());
}
}
Assertions.assertCondition(mCurrentActivity != null);
}
if (mCurrentActivity != null) {
Assertions.assertCondition(
activity == mCurrentActivity,
"Pausing an activity that is not the current activity, this is incorrect! "
+ "Current activity: "
+ mCurrentActivity.getClass().getSimpleName()
+ " "
+ "Paused activity: "
+ activity.getClass().getSimpleName());
}
onHostPause();
}
/**
* Use this method when the activity resumes to enable invoking the back button directly from JS.
*
* <p>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 #onHostDestroy} event it will
* clear the reference to that defaultBackButtonImpl.
*
* @param defaultBackButtonImpl a {@link DefaultHardwareBackBtnHandler} from an Activity that owns
* this instance of {@link ReactInstanceManager}.
*/
@ThreadConfined(UI)
public void onHostResume(
@Nullable Activity activity, DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
UiThreadUtil.assertOnUiThread();
mDefaultBackButtonImpl = defaultBackButtonImpl;
onHostResume(activity);
}
/** Use this method when the activity resumes. */
@ThreadConfined(UI)
public void onHostResume(@Nullable Activity activity) {
UiThreadUtil.assertOnUiThread();
mCurrentActivity = activity;
if (mUseDeveloperSupport) {
// Resume can be called from one of three different states:
// a) when activity was paused
// b) when activity has just been created
// c) when there is no activity
// In case of (a) the activity is attached to window and it is ok to add new views to it or
// open dialogs. In case of (b) there is often a slight delay before such a thing happens.
// As dev support manager can add views or open dialogs immediately after it gets enabled
// (e.g. in the case when JS bundle is being fetched in background) we only want to enable
// it once we know for sure the current activity is attached.
// We want to enable the various devsupport tools in case of (c) even without any activity
if (mCurrentActivity != null) {
// We check if activity is attached to window by checking if decor view is attached
final View decorView = mCurrentActivity.getWindow().getDecorView();
if (!ViewCompat.isAttachedToWindow(decorView)) {
decorView.addOnAttachStateChangeListener(
new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
// we can drop listener now that we know the view is attached
decorView.removeOnAttachStateChangeListener(this);
mDevSupportManager.setDevSupportEnabled(true);
}
@Override
public void onViewDetachedFromWindow(View v) {
// do nothing
}
});
} else {
// activity is attached to window, we can enable dev support immediately
mDevSupportManager.setDevSupportEnabled(true);
}
} else if (!mRequireActivity) {
// there is no activity, but we can enable dev support
mDevSupportManager.setDevSupportEnabled(true);
}
}
moveToResumedLifecycleState(false);
}
/**
* Call this from {@link Activity#onDestroy()}. This notifies any listening modules so they can do
* any necessary cleanup.
*
* @deprecated use {@link #onHostDestroy(Activity)} instead
*/
@ThreadConfined(UI)
@Deprecated
public void onHostDestroy() {
UiThreadUtil.assertOnUiThread();
if (mUseDeveloperSupport) {
mDevSupportManager.setDevSupportEnabled(false);
}
moveToBeforeCreateLifecycleState();
if (!mKeepActivity) {
mCurrentActivity = null;
}
}
/**
* Call this from {@link Activity#onDestroy()}. This notifies any listening modules so they can do
* any necessary cleanup. If the activity being destroyed is not the current activity, no modules
* are notified.
*
* @param activity the activity being destroyed
*/
@ThreadConfined(UI)
public void onHostDestroy(@Nullable Activity activity) {
// In some cases, Activity may (correctly) be null.
// See mRequireActivity flag.
if (activity == mCurrentActivity) {
onHostDestroy();
}
}
/** Temporary: due to T67035147, log sources of destroy calls. TODO T67035147: delete */
private void logOnDestroy() {
FLog.d(
TAG,
"ReactInstanceManager.destroy called",
new RuntimeException("ReactInstanceManager.destroy called"));
}
/** Destroy this React instance and the attached JS context. */
@ThreadConfined(UI)
public void destroy() {
UiThreadUtil.assertOnUiThread();
PrinterHolder.getPrinter().logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: Destroy");
logOnDestroy();
if (mHasStartedDestroying) {
FLog.e(
ReactConstants.TAG, "ReactInstanceManager.destroy called: bail out, already destroying");
return;
}
mHasStartedDestroying = true;
if (mUseDeveloperSupport) {
mDevSupportManager.setDevSupportEnabled(false);
mDevSupportManager.stopInspector();
}
moveToBeforeCreateLifecycleState();
mMemoryPressureRouter.destroy(mApplicationContext);
unregisterCxxErrorHandlerFunc();
mCreateReactContextThread = null;
synchronized (mAttachedReactRoots) {
synchronized (mReactContextLock) {
if (mCurrentReactContext != null) {
for (ReactRoot reactRoot : mAttachedReactRoots) {
// Fabric surfaces must be cleaned up when React Native is destroyed.
if (reactRoot.getUIManagerType() == UIManagerType.FABRIC) {
detachRootViewFromInstance(reactRoot, mCurrentReactContext);
}
}
mCurrentReactContext.destroy();
mCurrentReactContext = null;
}
}
}
// If the host has been invalidated, now that the current context/instance
// has been destroyed, we can safely destroy the host's inspector target.
if (mInstanceManagerInvalidated) {
if (mInspectorTarget != null) {
mInspectorTarget.close();
mInspectorTarget = null;
}
}
mHasStartedCreatingInitialContext = false;
if (!mKeepActivity) {
mCurrentActivity = null;
}
ResourceDrawableIdHelper.getInstance().clear();
mHasStartedDestroying = false;
synchronized (mHasStartedDestroying) {
mHasStartedDestroying.notifyAll();
}
synchronized (mPackages) {
mViewManagerNames = null;
}
FLog.d(ReactConstants.TAG, "ReactInstanceManager has been destroyed");
}
private synchronized void moveToResumedLifecycleState(boolean force) {
ReactContext currentContext = getCurrentReactContext();
if (currentContext != null) {
// we currently don't have an onCreate callback so we call onResume for both transitions
if (force
|| mLifecycleState == LifecycleState.BEFORE_RESUME
|| mLifecycleState == LifecycleState.BEFORE_CREATE) {
currentContext.onHostResume(mCurrentActivity);
}
}
mLifecycleState = LifecycleState.RESUMED;
}
private synchronized void moveToBeforeResumeLifecycleState() {
ReactContext currentContext = getCurrentReactContext();
if (currentContext != null) {
if (mLifecycleState == LifecycleState.BEFORE_CREATE) {
currentContext.onHostResume(mCurrentActivity);
currentContext.onHostPause();
} else if (mLifecycleState == LifecycleState.RESUMED) {
currentContext.onHostPause();
}
}
mLifecycleState = LifecycleState.BEFORE_RESUME;
}
private synchronized void moveToBeforeCreateLifecycleState() {
ReactContext currentContext = getCurrentReactContext();
if (currentContext != null) {
if (mLifecycleState == LifecycleState.RESUMED) {
currentContext.onHostPause();
mLifecycleState = LifecycleState.BEFORE_RESUME;
}
if (mLifecycleState == LifecycleState.BEFORE_RESUME) {
currentContext.onHostDestroy(mKeepActivity);
}
}
mLifecycleState = LifecycleState.BEFORE_CREATE;
}
private synchronized void moveReactContextToCurrentLifecycleState() {
if (mLifecycleState == LifecycleState.RESUMED) {
moveToResumedLifecycleState(true);
}
}
@ThreadConfined(UI)
public void onActivityResult(
Activity activity, int requestCode, int resultCode, @Nullable Intent data) {
ReactContext currentContext = getCurrentReactContext();
if (currentContext != null) {
currentContext.onActivityResult(activity, requestCode, resultCode, data);
}
}
@ThreadConfined(UI)
public void onWindowFocusChange(boolean hasFocus) {
UiThreadUtil.assertOnUiThread();
ReactContext currentContext = getCurrentReactContext();
if (currentContext != null) {
currentContext.onWindowFocusChange(hasFocus);
}
}
/** Call this from {@link Activity#onConfigurationChanged()}. */
@ThreadConfined(UI)
public void onConfigurationChanged(Context updatedContext, @Nullable Configuration newConfig) {
UiThreadUtil.assertOnUiThread();
ReactContext currentReactContext = getCurrentReactContext();
if (currentReactContext != null) {
AppearanceModule appearanceModule =
currentReactContext.getNativeModule(AppearanceModule.class);
if (appearanceModule != null) {
appearanceModule.onConfigurationChanged(updatedContext);
}
}
}
@ThreadConfined(UI)
public void showDevOptionsDialog() {
UiThreadUtil.assertOnUiThread();
mDevSupportManager.showDevOptionsDialog();
}
@ThreadConfined(UI)
private void clearReactRoot(ReactRoot reactRoot) {
UiThreadUtil.assertOnUiThread();
reactRoot.getState().compareAndSet(ReactRoot.STATE_STARTED, ReactRoot.STATE_STOPPED);
ViewGroup rootViewGroup = reactRoot.getRootViewGroup();
rootViewGroup.removeAllViews();
rootViewGroup.setId(View.NO_ID);
}
/**
* Attach given {@param reactRoot} to a catalyst instance manager and start JS application using
* JS module provided by {@link ReactRootView#getJSModuleName}. If the react context is currently
* being (re)-created, or if react context has not been created yet, the JS application associated
* with the provided reactRoot reactRoot will be started asynchronously, i.e this method won't
* block. This reactRoot will then be tracked by this manager and in case of catalyst instance
* restart it will be re-attached.
*
* @deprecated This method should be internal to ReactRootView and ReactInstanceManager
*/
@Deprecated
@ThreadConfined(UI)
public void attachRootView(ReactRoot reactRoot) {
UiThreadUtil.assertOnUiThread();
synchronized (mAttachedReactRoots) {
// Calling clearReactRoot is necessary to initialize the Id on reactRoot
// This is necessary independently if the RN Bridge has been initialized or not.
// Ideally reactRoot should be initialized with id == NO_ID
if (mAttachedReactRoots.add(reactRoot)) {
clearReactRoot(reactRoot);
} else {
FLog.e(ReactConstants.TAG, "ReactRoot was attached multiple times");
}
// If react context is being created in the background, JS application will be started
// automatically when creation completes, as reactRoot is part of the attached
// reactRoot list.
ReactContext currentContext = getCurrentReactContext();
if (mCreateReactContextThread == null && currentContext != null) {
attachRootViewToInstance(reactRoot);
}
}
}
/**
* Detach given {@param reactRoot} from current catalyst instance. It's safe to call this method
* multiple times on the same {@param reactRoot} - in that case view will be detached with the
* first call.
*
* @deprecated This method should be internal to ReactRootView and ReactInstanceManager
*/
@Deprecated
@ThreadConfined(UI)
public void detachRootView(ReactRoot reactRoot) {
UiThreadUtil.assertOnUiThread();
if (!mAttachedReactRoots.remove(reactRoot)) {
return;
}
ReactContext reactContext = mCurrentReactContext;
if (reactContext != null && reactContext.hasActiveReactInstance()) {
detachRootViewFromInstance(reactRoot, reactContext);
}
}
/** Uses configured {@link ReactPackage} instances to create all view managers. */
public List<ViewManager> getOrCreateViewManagers(
ReactApplicationContext catalystApplicationContext) {
ReactMarker.logMarker(CREATE_VIEW_MANAGERS_START);
Systrace.beginSection(TRACE_TAG_REACT, "createAllViewManagers");
try {
if (mViewManagers == null) {
synchronized (mPackages) {
if (mViewManagers == null) {
ArrayList<ViewManager> viewManagers = new ArrayList<>();
for (ReactPackage reactPackage : mPackages) {
viewManagers.addAll(reactPackage.createViewManagers(catalystApplicationContext));
}
mViewManagers = viewManagers;
return mViewManagers;
}
}
}
return mViewManagers;
} finally {
Systrace.endSection(TRACE_TAG_REACT);
ReactMarker.logMarker(CREATE_VIEW_MANAGERS_END);
}
}
public @Nullable ViewManager createViewManager(String viewManagerName) {
ReactApplicationContext context;
synchronized (mReactContextLock) {
context = (ReactApplicationContext) getCurrentReactContext();
if (context == null || !context.hasActiveReactInstance()) {
return null;
}
}
synchronized (mPackages) {
for (ReactPackage reactPackage : mPackages) {
if (reactPackage instanceof ViewManagerOnDemandReactPackage) {
ViewManager viewManager =
((ViewManagerOnDemandReactPackage) reactPackage)
.createViewManager(context, viewManagerName);
if (viewManager != null) {
return viewManager;
}
}
}
}
return null;
}
public Collection<String> getViewManagerNames() {
Systrace.beginSection(TRACE_TAG_REACT, "ReactInstanceManager.getViewManagerNames");
try {
Collection<String> viewManagerNames = mViewManagerNames;
if (viewManagerNames != null) {
return viewManagerNames;
}
ReactApplicationContext context;
synchronized (mReactContextLock) {
context = (ReactApplicationContext) getCurrentReactContext();
if (context == null || !context.hasActiveReactInstance()) {
FLog.w(ReactConstants.TAG, "Calling getViewManagerNames without active context");
return Collections.emptyList();
}
}
synchronized (mPackages) {
if (mViewManagerNames == null) {
Set<String> uniqueNames = new HashSet<>();
for (ReactPackage reactPackage : mPackages) {
SystraceMessage.beginSection(TRACE_TAG_REACT, "ReactInstanceManager.getViewManagerName")
.arg("Package", reactPackage.getClass().getSimpleName())
.flush();
if (reactPackage instanceof ViewManagerOnDemandReactPackage) {
Collection<String> names =
((ViewManagerOnDemandReactPackage) reactPackage).getViewManagerNames(context);
// When converting this class to Kotlin, you need to retain this null check
// or wrap around a try/catch otherwise this will cause a crash for OSS libraries
// that are not migrated to Kotlin yet and are returning null for
// `getViewManagerNames`
if (names != null) {
uniqueNames.addAll(names);
}
} else {
FLog.w(
ReactConstants.TAG,
"Package %s is not a ViewManagerOnDemandReactPackage, view managers will not be"
+ " loaded",
reactPackage.getClass().getSimpleName());
}
Systrace.endSection(TRACE_TAG_REACT);
}
mViewManagerNames = uniqueNames;
}
return mViewManagerNames;
}
} finally {
Systrace.endSection(TRACE_TAG_REACT);
}
}
/** Add a listener to be notified of react instance events. */
public void addReactInstanceEventListener(
com.facebook.react.ReactInstanceEventListener listener) {
mReactInstanceEventListeners.add(listener);
}
/** Remove a listener previously added with {@link #addReactInstanceEventListener}. */
public void removeReactInstanceEventListener(
com.facebook.react.ReactInstanceEventListener listener) {
mReactInstanceEventListeners.remove(listener);
}
/**
* @return current ReactApplicationContext
*/
public @Nullable ReactContext getCurrentReactContext() {
synchronized (mReactContextLock) {
return mCurrentReactContext;
}
}
public LifecycleState getLifecycleState() {
return mLifecycleState;
}
public String getJsExecutorName() {
return mJavaScriptExecutorFactory.toString();
}
/**
* Permanently destroys the ReactInstanceManager, including the CatalystInstance (if any). The
* application MUST NOT call any further methods on an invalidated ReactInstanceManager.
*
* <p>Applications where the ReactInstanceManager may be destroyed before the end of the process
* SHOULD call invalidate() before releasing the reference to the ReactInstanceManager, to ensure
* resources are freed in a timely manner.
*
* <p>NOTE: This method is designed for complex integrations. Integrators MAY instead hold a
* long-lived reference to a single ReactInstanceManager for the lifetime of the Application,
* without ever calling invalidate(). This is explicitly allowed.
*/
@ThreadConfined(UI)
public void invalidate() {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.invalidate()");
mInstanceManagerInvalidated = true;
destroy();
}
@ThreadConfined(UI)
private void onJSBundleLoadedFromServer() {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.onJSBundleLoadedFromServer()");
JSBundleLoader bundleLoader =
JSBundleLoader.createCachedBundleFromNetworkLoader(
mDevSupportManager.getSourceUrl(), mDevSupportManager.getDownloadedJSBundleFile());
recreateReactContextInBackground(mJavaScriptExecutorFactory, bundleLoader);
}
@ThreadConfined(UI)
private void recreateReactContextInBackground(
JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.recreateReactContextInBackground()");
UiThreadUtil.assertOnUiThread();
final ReactContextInitParams initParams =
new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);
if (mCreateReactContextThread == null) {
runCreateReactContextOnNewThread(initParams);
} else {
mPendingReactContextInitParams = initParams;
}
}
@ThreadConfined(UI)
private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.runCreateReactContextOnNewThread()");
UiThreadUtil.assertOnUiThread();
Assertions.assertCondition(
!mInstanceManagerInvalidated,
"Cannot create a new React context on an invalidated ReactInstanceManager");
// Mark start of bridge loading
ReactMarker.logMarker(ReactMarkerConstants.REACT_BRIDGE_LOADING_START);
synchronized (mAttachedReactRoots) {
synchronized (mReactContextLock) {
if (mCurrentReactContext != null) {
tearDownReactContext(mCurrentReactContext);
mCurrentReactContext = null;
}
}
}
mCreateReactContextThread =
new Thread(
null,
() -> {
ReactMarker.logMarker(REACT_CONTEXT_THREAD_END);
synchronized (ReactInstanceManager.this.mHasStartedDestroying) {
while (ReactInstanceManager.this.mHasStartedDestroying) {
try {
ReactInstanceManager.this.mHasStartedDestroying.wait();
} catch (InterruptedException e) {
continue;
}
}
}
// As destroy() may have run and set this to false, ensure that it is true before we
// create
mHasStartedCreatingInitialContext = true;
final ReactApplicationContext reactApplicationContext;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
ReactMarker.logMarker(VM_INIT);
reactApplicationContext =
createReactContext(
initParams.getJsExecutorFactory().create(), initParams.getJsBundleLoader());
} catch (Exception e) {
// Reset state and bail out. This lets us try again later.
mHasStartedCreatingInitialContext = false;
mCreateReactContextThread = null;
mDevSupportManager.handleException(e);
return;
}
try {
mCreateReactContextThread = null;
ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_START);
final Runnable maybeRecreateReactContextRunnable =
() -> {
if (mPendingReactContextInitParams != null) {
runCreateReactContextOnNewThread(mPendingReactContextInitParams);
mPendingReactContextInitParams = null;
}
};
Runnable setupReactContextRunnable =
() -> {
try {
setupReactContext(reactApplicationContext);
} catch (Exception e) {
mDevSupportManager.handleException(e);
}
};
reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable);
UiThreadUtil.runOnUiThread(maybeRecreateReactContextRunnable);
} catch (Exception e) {
mDevSupportManager.handleException(e);
}
},
"create_react_context");
ReactMarker.logMarker(REACT_CONTEXT_THREAD_START);
mCreateReactContextThread.start();
}
private void setupReactContext(final ReactApplicationContext reactContext) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.setupReactContext()");
ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_END);
ReactMarker.logMarker(SETUP_REACT_CONTEXT_START);
Systrace.beginSection(TRACE_TAG_REACT, "setupReactContext");
synchronized (mAttachedReactRoots) {
synchronized (mReactContextLock) {
mCurrentReactContext = Assertions.assertNotNull(reactContext);
}
CatalystInstance catalystInstance =
Assertions.assertNotNull(reactContext.getCatalystInstance());
catalystInstance.initialize();
mDevSupportManager.onNewReactContextCreated(reactContext);
mMemoryPressureRouter.addMemoryPressureListener(catalystInstance);
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_START);
for (ReactRoot reactRoot : mAttachedReactRoots) {
attachRootViewToInstance(reactRoot);
}
ReactMarker.logMarker(ATTACH_MEASURED_ROOT_VIEWS_END);
}
// There is a race condition here - `finalListeners` can contain null entries
// See usage below for more details.
com.facebook.react.ReactInstanceEventListener[] listeners =
new com.facebook.react.ReactInstanceEventListener[mReactInstanceEventListeners.size()];
final com.facebook.react.ReactInstanceEventListener[] finalListeners =
mReactInstanceEventListeners.toArray(listeners);
UiThreadUtil.runOnUiThread(
() -> {
moveReactContextToCurrentLifecycleState();
for (com.facebook.react.ReactInstanceEventListener listener : finalListeners) {
// Sometimes this listener is null - probably due to race
// condition between allocating listeners with a certain
// size, and getting a `final` version of the array on
// the following line.
if (listener != null) {
listener.onReactContextInitialized(reactContext);
}
}
});
reactContext.runOnJSQueueThread(
() -> {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
ReactMarker.logMarker(CHANGE_THREAD_PRIORITY, "js_default");
});
reactContext.runOnNativeModulesQueueThread(
() -> Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT));
Systrace.endSection(TRACE_TAG_REACT);
ReactMarker.logMarker(SETUP_REACT_CONTEXT_END);
// Mark end of bridge loading
ReactMarker.logMarker(ReactMarkerConstants.REACT_BRIDGE_LOADING_END);
}
private void attachRootViewToInstance(final ReactRoot reactRoot) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
if (!reactRoot.getState().compareAndSet(ReactRoot.STATE_STOPPED, ReactRoot.STATE_STARTED)) {
// Already started
return;
}
Systrace.beginSection(TRACE_TAG_REACT, "attachRootViewToInstance");
@Nullable
UIManager uiManager =
UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
// If we can't get a UIManager something has probably gone horribly wrong
if (uiManager == null) {
throw new IllegalStateException(
"Unable to attach a rootView to ReactInstance when UIManager is not properly"
+ " initialized.");
}
@Nullable Bundle initialProperties = reactRoot.getAppProperties();
final int rootTag;
if (reactRoot.getUIManagerType() == FABRIC) {
rootTag =
uiManager.startSurface(
reactRoot.getRootViewGroup(),
reactRoot.getJSModuleName(),
initialProperties == null
? new WritableNativeMap()
: Arguments.fromBundle(initialProperties),
reactRoot.getWidthMeasureSpec(),
reactRoot.getHeightMeasureSpec());
reactRoot.setShouldLogContentAppeared(true);
} else {
rootTag =
uiManager.addRootView(
reactRoot.getRootViewGroup(),
initialProperties == null
? new WritableNativeMap()
: Arguments.fromBundle(initialProperties));
reactRoot.setRootViewTag(rootTag);
reactRoot.runApplication();
}
Systrace.beginAsyncSection(TRACE_TAG_REACT, "pre_rootView.onAttachedToReactInstance", rootTag);
UiThreadUtil.runOnUiThread(
() -> {
Systrace.endAsyncSection(
TRACE_TAG_REACT, "pre_rootView.onAttachedToReactInstance", rootTag);
reactRoot.onStage(ReactStage.ON_ATTACH_TO_INSTANCE);
});
Systrace.endSection(TRACE_TAG_REACT);
}
private void detachRootViewFromInstance(ReactRoot reactRoot, ReactContext reactContext) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.detachRootViewFromInstance()");
UiThreadUtil.assertOnUiThread();
if (!reactRoot.getState().compareAndSet(ReactRoot.STATE_STARTED, ReactRoot.STATE_STOPPED)) {
// ReactRoot was already stopped
return;
}
@UIManagerType int uiManagerType = reactRoot.getUIManagerType();
if (uiManagerType == UIManagerType.FABRIC) {
// Stop surface in Fabric.
// Calling FabricUIManager.stopSurface causes the C++ Binding.stopSurface
// to be called synchronously over the JNI, which causes an empty tree
// to be committed via the Scheduler, which will cause mounting instructions
// to be queued up and synchronously executed to delete and remove
// all the views in the hierarchy.
final int surfaceId = reactRoot.getRootViewTag();
if (surfaceId != View.NO_ID) {
UIManager uiManager = UIManagerHelper.getUIManager(reactContext, uiManagerType);
if (uiManager != null) {
uiManager.stopSurface(surfaceId);
} else {
FLog.w(ReactConstants.TAG, "Failed to stop surface, UIManager has already gone away");
}
} else {
ReactSoftExceptionLogger.logSoftException(
TAG,
new RuntimeException(
"detachRootViewFromInstance called with ReactRootView with invalid id"));
}
clearReactRoot(reactRoot);
} else {
reactContext
.getCatalystInstance()
.getJSModule(AppRegistry.class)
.unmountApplicationComponentAtRootTag(reactRoot.getRootViewTag());
}
}
@ThreadConfined(UI)
private void tearDownReactContext(ReactContext reactContext) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.tearDownReactContext()");
UiThreadUtil.assertOnUiThread();
if (mLifecycleState == LifecycleState.RESUMED) {
reactContext.onHostPause();
}
synchronized (mAttachedReactRoots) {
for (ReactRoot reactRoot : mAttachedReactRoots) {
detachRootViewFromInstance(reactRoot, reactContext);
}
}
// Remove memory pressure listener before tearing down react context
// We cannot access the CatalystInstance after destroying the ReactContext.
mMemoryPressureRouter.removeMemoryPressureListener(reactContext.getCatalystInstance());
reactContext.destroy();
mDevSupportManager.onReactInstanceDestroyed(reactContext);
}
/**
* @return instance of {@link ReactContext} configured a {@link CatalystInstance} set
*/
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
FLog.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()");
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
final BridgeReactContext reactContext = new BridgeReactContext(mApplicationContext);
JSExceptionHandler exceptionHandler =
mJSExceptionHandler != null ? mJSExceptionHandler : mDevSupportManager;
reactContext.setJSExceptionHandler(exceptionHandler);
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages);
CatalystInstanceImpl.Builder catalystInstanceBuilder =
new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
.setJSBundleLoader(jsBundleLoader)
.setJSExceptionHandler(exceptionHandler)
.setInspectorTarget(getOrCreateInspectorTarget());
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
// CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp
Systrace.beginSection(TRACE_TAG_REACT, "createCatalystInstance");
final CatalystInstance catalystInstance;
try {
catalystInstance = catalystInstanceBuilder.build();
} finally {
Systrace.endSection(TRACE_TAG_REACT);
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_END);
}
reactContext.initializeWithInstance(catalystInstance);
// On Old Architecture, we need to initialize the Native Runtime Scheduler so that
// the `nativeRuntimeScheduler` object is registered on JS.
// On New Architecture, this is normally triggered by instantiate a TurboModuleManager.
// Here we invoke getRuntimeScheduler() to trigger the creation of it regardless of the
// architecture so it will always be there.
catalystInstance.getRuntimeScheduler();
if (ReactNativeNewArchitectureFeatureFlags.useTurboModules() && mTMMDelegateBuilder != null) {
TurboModuleManagerDelegate tmmDelegate =
mTMMDelegateBuilder
.setPackages(mPackages)
.setReactApplicationContext(reactContext)
.build();
TurboModuleManager turboModuleManager =
new TurboModuleManager(
catalystInstance.getRuntimeExecutor(),
tmmDelegate,
catalystInstance.getJSCallInvokerHolder(),
catalystInstance.getNativeMethodCallInvokerHolder());
catalystInstance.setTurboModuleRegistry(turboModuleManager);
// Eagerly initialize TurboModules
for (String moduleName : turboModuleManager.getEagerInitModuleNames()) {
turboModuleManager.getModule(moduleName);
}
}
if (mUIManagerProvider != null) {
UIManager uiManager = mUIManagerProvider.createUIManager(reactContext);
if (uiManager != null) {
catalystInstance.setFabricUIManager(uiManager);
// Initialize the UIManager
uiManager.initialize();
catalystInstance.setFabricUIManager(uiManager);
}
}
if (mBridgeIdleDebugListener != null) {
catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
}
if (BuildConfig.ENABLE_PERFETTO || Systrace.isTracing(TRACE_TAG_REACT)) {
catalystInstance.setGlobalVariable("__RCTProfileIsProfiling", "true");
}
ReactMarker.logMarker(ReactMarkerConstants.PRE_RUN_JS_BUNDLE_START);
Systrace.beginSection(TRACE_TAG_REACT, "runJSBundle");
catalystInstance.runJSBundle();
Systrace.endSection(TRACE_TAG_REACT);
return reactContext;
}
private NativeModuleRegistry processPackages(
ReactApplicationContext reactContext, List<ReactPackage> packages) {
NativeModuleRegistryBuilder nativeModuleRegistryBuilder =
new NativeModuleRegistryBuilder(reactContext);
ReactMarker.logMarker(PROCESS_PACKAGES_START);
synchronized (mPackages) {
for (ReactPackage reactPackage : packages) {
Systrace.beginSection(TRACE_TAG_REACT, "createAndProcessCustomReactPackage");
try {
processPackage(reactPackage, nativeModuleRegistryBuilder);
} finally {
Systrace.endSection(TRACE_TAG_REACT);
}
}
}
ReactMarker.logMarker(PROCESS_PACKAGES_END);
ReactMarker.logMarker(BUILD_NATIVE_MODULE_REGISTRY_START);
Systrace.beginSection(TRACE_TAG_REACT, "buildNativeModuleRegistry");
NativeModuleRegistry nativeModuleRegistry;
try {
nativeModuleRegistry = nativeModuleRegistryBuilder.build();
} finally {
Systrace.endSection(TRACE_TAG_REACT);
ReactMarker.logMarker(BUILD_NATIVE_MODULE_REGISTRY_END);
}
return nativeModuleRegistry;
}
private void processPackage(
ReactPackage reactPackage, NativeModuleRegistryBuilder nativeModuleRegistryBuilder) {
SystraceMessage.beginSection(TRACE_TAG_REACT, "processPackage")
.arg("className", reactPackage.getClass().getSimpleName())
.flush();
if (reactPackage instanceof ReactPackageLogger) {
((ReactPackageLogger) reactPackage).startProcessPackage();
}
nativeModuleRegistryBuilder.processPackage(reactPackage);
if (reactPackage instanceof ReactPackageLogger) {
((ReactPackageLogger) reactPackage).endProcessPackage();
}
SystraceMessage.endSection(TRACE_TAG_REACT).flush();
}
private static class InspectorTargetDelegateImpl
implements ReactInstanceManagerInspectorTarget.TargetDelegate {
// This weak reference breaks the cycle between the C++ HostTarget and the
// Java ReactInstanceManager, preventing memory leaks in apps that create
// multiple ReactInstanceManagers over time.
private WeakReference<ReactInstanceManager> mReactInstanceManagerWeak;
public InspectorTargetDelegateImpl(ReactInstanceManager inspectorTarget) {
mReactInstanceManagerWeak = new WeakReference<ReactInstanceManager>(inspectorTarget);
}
@Override
public Map<String, String> getMetadata() {
ReactInstanceManager reactInstanceManager = mReactInstanceManagerWeak.get();
return AndroidInfoHelpers.getInspectorHostMetadata(
reactInstanceManager != null ? reactInstanceManager.mApplicationContext : null);
}
@Override
public void onReload() {
UiThreadUtil.runOnUiThread(
() -> {
ReactInstanceManager reactInstanceManager = mReactInstanceManagerWeak.get();
if (reactInstanceManager != null) {
reactInstanceManager.mDevSupportManager.handleReloadJS();
}
});
}
@Override
public void onSetPausedInDebuggerMessage(@Nullable String message) {
ReactInstanceManager reactInstanceManager = mReactInstanceManagerWeak.get();
if (reactInstanceManager == null) {
return;
}
if (message == null) {
reactInstanceManager.mDevSupportManager.hidePausedInDebuggerOverlay();
} else {
reactInstanceManager.mDevSupportManager.showPausedInDebuggerOverlay(
message,
new PausedInDebuggerOverlayCommandListener() {
@Override
public void onResume() {
UiThreadUtil.assertOnUiThread();
if (reactInstanceManager.mInspectorTarget != null) {
reactInstanceManager.mInspectorTarget.sendDebuggerResumeCommand();
}
}
});
}
}
@Override
public void loadNetworkResource(String url, InspectorNetworkRequestListener listener) {
InspectorNetworkHelper.loadNetworkResource(url, listener);
}
}
private @Nullable ReactInstanceManagerInspectorTarget getOrCreateInspectorTarget() {
if (mInspectorTarget == null && InspectorFlags.getFuseboxEnabled()) {
mInspectorTarget =
new ReactInstanceManagerInspectorTarget(new InspectorTargetDelegateImpl(this));
}
return mInspectorTarget;
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!