mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Call stopSurface when ReactRootView is unregistered
Summary: In the past, in Fabric (Android), we never called stopSurface. Ever! This is bad for memory and can cause other issues, so... let's not do that. Instead, when the ReactRootView is being torn down, we check the View ID to see if it's a Fabric RootView, and if it is, we call Fabric's stopSurface method. Fabric stopSurface only has impact on (1) Fabric mount instructions being executed after that point and (2) tells JS to stop running the surface, on the JS thread, asynchronously. Anecdotally it looks like all the MountItems involved in deleting and removing views from the hierarchy are executed before stopSurface is called. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D21965837 fbshipit-source-id: 5169c5a1e339fd9e016ae1234d8389b2bd30be70
This commit is contained in:
committed by
Facebook GitHub Bot
parent
1c92b1cff6
commit
03174f1cad
@@ -431,6 +431,23 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
@ThreadConfined(UI)
|
||||
public void unmountReactApplication() {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
// 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.
|
||||
if (mReactInstanceManager != null) {
|
||||
final ReactContext reactApplicationContext = mReactInstanceManager.getCurrentReactContext();
|
||||
if (reactApplicationContext != null && getUIManagerType() == FABRIC) {
|
||||
@Nullable
|
||||
UIManager uiManager =
|
||||
UIManagerHelper.getUIManager(reactApplicationContext, getUIManagerType());
|
||||
if (uiManager != null) {
|
||||
uiManager.stopSurface(this.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mReactInstanceManager != null && mIsAttachedToInstance) {
|
||||
mReactInstanceManager.detachRootView(this);
|
||||
|
||||
@@ -32,6 +32,13 @@ public interface UIManager extends JSIModule, PerformanceCounter {
|
||||
int widthMeasureSpec,
|
||||
int heightMeasureSpec);
|
||||
|
||||
/**
|
||||
* Stop a surface from running in JS and clears up native memory usage. Assumes that the native
|
||||
* View hierarchy has already been cleaned up. Fabric-only.
|
||||
*/
|
||||
@AnyThread
|
||||
void stopSurface(final int surfaceId);
|
||||
|
||||
/**
|
||||
* Updates the layout specs of the RootShadowNode based on the Measure specs received by
|
||||
* parameters.
|
||||
|
||||
@@ -242,6 +242,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
|
||||
@AnyThread
|
||||
@ThreadConfined(ANY)
|
||||
@Override
|
||||
public void stopSurface(int surfaceID) {
|
||||
mBinding.stopSurface(surfaceID);
|
||||
mReactContextForRootTag.remove(surfaceID);
|
||||
|
||||
@@ -437,6 +437,11 @@ public class UIManagerModule extends ReactContextBaseJavaModule
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSurface(final int surfaceId) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** Unregisters a new root view. */
|
||||
@ReactMethod
|
||||
public void removeRootView(int rootViewTag) {
|
||||
|
||||
Reference in New Issue
Block a user