Skip to content

Commit a3db352

Browse files
motiz88facebook-github-bot
authored andcommitted
Add invalidate() method to ReactHost and ReactInstanceManager (#45081)
Summary: Pull Request resolved: #45081 Changelog: [Android][Added] Add `invalidate()` method to ReactHost and ReactInstanceManager Adds an `invalidate()` method to both `ReactHost` (Bridgeless) and `ReactInstanceManager` (Bridge). This method is an *optional* signal that the application is about to permanently stop using the Host, and that the Host can therefore fully clean up any resources it's holding. Reusing a Host after it's invalidated is illegal and will trigger a Java assertion. The plan: 1. **[This diff]**: Add the basic `invalidate()` functionality. 2. [Upcoming diff]: Add `invalidate()` call sites where it makes sense in core 3. [Upcoming diff]: Keep the Fusebox debugging target registered until the Host is explicitly invalidated. Reviewed By: tdn120 Differential Revision: D58811090 fbshipit-source-id: 79b607dcc74de38b85fc0ebb4c640b9654595c9a
1 parent d11a7b0 commit a3db352

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

packages/react-native/ReactAndroid/api/ReactAndroid.api

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ public abstract interface class com/facebook/react/ReactHost {
216216
public abstract fun getLifecycleState ()Lcom/facebook/react/common/LifecycleState;
217217
public abstract fun getMemoryPressureRouter ()Lcom/facebook/react/MemoryPressureRouter;
218218
public abstract fun getReactQueueConfiguration ()Lcom/facebook/react/bridge/queue/ReactQueueConfiguration;
219+
public abstract fun invalidate ()V
219220
public abstract fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V
220221
public abstract fun onBackPressed ()Z
221222
public abstract fun onConfigurationChanged (Landroid/content/Context;)V
@@ -254,6 +255,7 @@ public class com/facebook/react/ReactInstanceManager {
254255
public fun getViewManagerNames ()Ljava/util/Collection;
255256
public fun handleCxxError (Ljava/lang/Exception;)V
256257
public fun hasStartedCreatingInitialContext ()Z
258+
public fun invalidate ()V
257259
public fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V
258260
public fun onBackPressed ()V
259261
public fun onConfigurationChanged (Landroid/content/Context;Landroid/content/res/Configuration;)V
@@ -3798,6 +3800,7 @@ public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/React
37983800
public fun getLifecycleState ()Lcom/facebook/react/common/LifecycleState;
37993801
public fun getMemoryPressureRouter ()Lcom/facebook/react/MemoryPressureRouter;
38003802
public fun getReactQueueConfiguration ()Lcom/facebook/react/bridge/queue/ReactQueueConfiguration;
3803+
public fun invalidate ()V
38013804
public fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V
38023805
public fun onBackPressed ()Z
38033806
public fun onConfigurationChanged (Landroid/content/Context;)V

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,20 @@ public interface ReactHost {
115115
*/
116116
public fun destroy(reason: String, ex: Exception?): TaskInterface<Void>
117117

118+
/**
119+
* Permanently destroys the ReactHost, including the ReactInstance (if any). The application MUST
120+
* NOT call any further methods on an invalidated ReactHost.
121+
*
122+
* Applications where the ReactHost may be destroyed before the end of the process SHOULD call
123+
* invalidate() before releasing the reference to the ReactHost, to ensure resources are freed in
124+
* a timely manner.
125+
*
126+
* NOTE: This method is designed for complex integrations. Integrators MAY instead hold a
127+
* long-lived reference to a single ReactHost for the lifetime of the Application, without ever
128+
* calling invalidate(). This is explicitly allowed.
129+
*/
130+
public fun invalidate()
131+
118132
/* To be called when the host activity receives an activity result. */
119133
public fun onActivityResult(
120134
activity: Activity,

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ public interface ReactInstanceEventListener
196196
private final @Nullable ReactPackageTurboModuleManagerDelegate.Builder mTMMDelegateBuilder;
197197
private List<ViewManager> mViewManagers;
198198
private boolean mUseFallbackBundle = true;
199+
private volatile boolean mInstanceManagerInvalidated = false;
199200

200201
private class ReactContextInitParams {
201202
private final JavaScriptExecutorFactory mJsExecutorFactory;
@@ -1083,6 +1084,25 @@ public String getJsExecutorName() {
10831084
return mJavaScriptExecutorFactory.toString();
10841085
}
10851086

1087+
/**
1088+
* Permanently destroys the ReactInstanceManager, including the CatalystInstance (if any). The
1089+
* application MUST NOT call any further methods on an invalidated ReactInstanceManager.
1090+
*
1091+
* <p>Applications where the ReactInstanceManager may be destroyed before the end of the process
1092+
* SHOULD call invalidate() before releasing the reference to the ReactInstanceManager, to ensure
1093+
* resources are freed in a timely manner.
1094+
*
1095+
* <p>NOTE: This method is designed for complex integrations. Integrators MAY instead hold a
1096+
* long-lived reference to a single ReactInstanceManager for the lifetime of the Application,
1097+
* without ever calling invalidate(). This is explicitly allowed.
1098+
*/
1099+
@ThreadConfined(UI)
1100+
public void invalidate() {
1101+
FLog.d(ReactConstants.TAG, "ReactInstanceManager.invalidate()");
1102+
mInstanceManagerInvalidated = true;
1103+
destroy();
1104+
}
1105+
10861106
@ThreadConfined(UI)
10871107
private void onReloadWithJSDebugger(JavaJSExecutor.Factory jsExecutorFactory) {
10881108
FLog.d(ReactConstants.TAG, "ReactInstanceManager.onReloadWithJSDebugger()");
@@ -1382,7 +1402,11 @@ private void tearDownReactContext(ReactContext reactContext) {
13821402
private ReactApplicationContext createReactContext(
13831403
JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
13841404
FLog.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()");
1405+
Assertions.assertCondition(
1406+
!mInstanceManagerInvalidated,
1407+
"Cannot create a new React context on an invalidated ReactInstanceManager");
13851408
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
1409+
13861410
final BridgeReactContext reactContext = new BridgeReactContext(mApplicationContext);
13871411

13881412
JSExceptionHandler exceptionHandler =

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ public class ReactHostImpl implements ReactHost {
133133

134134
private @Nullable ReactHostInspectorTarget mReactHostInspectorTarget;
135135

136+
private volatile boolean mHostInvalidated = false;
137+
136138
public ReactHostImpl(
137139
Context context,
138140
ReactHostDelegate delegate,
@@ -1047,6 +1049,9 @@ private Task<ReactInstance> getOrCreateReactInstanceTask() {
10471049
return mCreateReactInstanceTaskRef.getOrCreate(
10481050
() -> {
10491051
log(method, "Start");
1052+
Assertions.assertCondition(
1053+
!mHostInvalidated, "Cannot start a new ReactInstance on an invalidated ReactHost");
1054+
10501055
ReactMarker.logMarker(
10511056
ReactMarkerConstants.REACT_BRIDGELESS_LOADING_START, BRIDGELESS_MARKER_INSTANCE_KEY);
10521057

@@ -1724,4 +1729,11 @@ private void unregisterInstanceFromInspector(final @Nullable ReactInstance react
17241729
destroyInspectorHostTarget();
17251730
}
17261731
}
1732+
1733+
@Override
1734+
public void invalidate() {
1735+
FLog.d(TAG, "ReactHostImpl.invalidate()");
1736+
mHostInvalidated = true;
1737+
destroy("ReactHostImpl.invalidate()", null);
1738+
}
17271739
}

0 commit comments

Comments
 (0)