From c5e7cd4ad96f468e9c5e2966e5fa5d599daa3e00 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Fri, 19 May 2023 09:25:56 -0700 Subject: [PATCH] Call invalidate on ViewManager on context destroy (#37481) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/37481 ViewManagers inherit from BaseJavaModule so we should honour the same lifecycle for them as we do for native modules, which is to call `invalidate` / `onCatalystInstanceDestroy` when the ReactContext is destroyed. This allows the ViewManager to do any cleanup which cannot happen at the View level. Changelog: [Android][Fixed] ViewManagers now receive an invalidate callback Reviewed By: cortinico Differential Revision: D45945678 fbshipit-source-id: 27c26d951b50a734c42eb033a46e599ef939e29f --- .../react/fabric/FabricUIManager.java | 1 + .../react/uimanager/UIImplementation.java | 1 + .../react/uimanager/ViewManagerRegistry.java | 28 +++++++++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index f4e9e6e308e5a2..f9057468f37dc7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -421,6 +421,7 @@ public void onCatalystInstanceDestroy() { mEventDispatcher.unregisterEventEmitter(FABRIC); mReactApplicationContext.unregisterComponentCallbacks(mViewManagerRegistry); + mViewManagerRegistry.invalidate(); // Remove lifecycle listeners (onHostResume, onHostPause) since the FabricUIManager is going // away. Then stop the mDispatchUIFrameCallback false will cause the choreographer diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java index ed4ec63c05d5b3..f15004e38e91d2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java @@ -792,6 +792,7 @@ public void onHostDestroy() {} public void onCatalystInstanceDestroyed() { mViewOperationsEnabled = false; + mViewManagers.invalidate(); } public void setViewHierarchyUpdateDebugListener( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java index 995f6eea70333a..1f3c219250a71f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java @@ -103,12 +103,28 @@ public void onSurfaceStopped(final int surfaceId) { viewManagers = new ArrayList<>(mViewManagers.values()); } Runnable runnable = - new Runnable() { - @Override - public void run() { - for (ViewManager viewManager : viewManagers) { - viewManager.onSurfaceStopped(surfaceId); - } + () -> { + for (ViewManager viewManager : viewManagers) { + viewManager.onSurfaceStopped(surfaceId); + } + }; + if (UiThreadUtil.isOnUiThread()) { + runnable.run(); + } else { + UiThreadUtil.runOnUiThread(runnable); + } + } + + /** Called on instance destroy */ + public void invalidate() { + final List viewManagers; + synchronized (this) { + viewManagers = new ArrayList<>(mViewManagers.values()); + } + Runnable runnable = + () -> { + for (ViewManager viewManager : viewManagers) { + viewManager.invalidate(); } }; if (UiThreadUtil.isOnUiThread()) {