Skip to content

Commit a1f6b4d

Browse files
javachefacebook-github-bot
authored andcommitted
Synchronize access to ViewManagerRegistry
Summary: Found that we may do multiple allocations of the same ViewManager instance since ViewManagers are both accessed from the UI thread (mounting views) and from the Fabric background thread (for measuring Text), which could lead to multiple instances of the same ViewManager to be created. As far as I can tell, this issue was harmless since our ViewManager constructors don't have side-effects, but not ideal. Changelog: [Internall] Reviewed By: rshest Differential Revision: D43661306 fbshipit-source-id: 37ef82d41d43c334fdc6cfbeffb225bba87c668e
1 parent 729dcf6 commit a1f6b4d

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerRegistry.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import androidx.annotation.Nullable;
1313
import com.facebook.react.bridge.UiThreadUtil;
1414
import com.facebook.react.common.MapBuilder;
15+
import java.util.ArrayList;
1516
import java.util.List;
1617
import java.util.Map;
1718

@@ -51,7 +52,7 @@ public ViewManagerRegistry(Map<String, ViewManager> viewManagerMap) {
5152
* view manager registered for the className received as a parameter.
5253
* @return the {@link ViewManager} registered to the className received as a parameter
5354
*/
54-
public ViewManager get(String className) {
55+
public synchronized ViewManager get(String className) {
5556
ViewManager viewManager = mViewManagers.get(className);
5657
if (viewManager != null) {
5758
return viewManager;
@@ -84,7 +85,7 @@ public ViewManager get(String className) {
8485
* there is no ViewManager associated to the className received as a parameter.
8586
*/
8687
@Nullable
87-
ViewManager getViewManagerIfExists(String className) {
88+
/* package */ synchronized ViewManager getViewManagerIfExists(String className) {
8889
ViewManager viewManager = mViewManagers.get(className);
8990
if (viewManager != null) {
9091
return viewManager;
@@ -97,12 +98,16 @@ ViewManager getViewManagerIfExists(String className) {
9798

9899
/** Send lifecycle signal to all ViewManagers that StopSurface has been called. */
99100
public void onSurfaceStopped(final int surfaceId) {
101+
List<ViewManager> viewManagers;
102+
synchronized (this) {
103+
viewManagers = new ArrayList<>(mViewManagers.values());
104+
}
100105
Runnable runnable =
101106
new Runnable() {
102107
@Override
103108
public void run() {
104-
for (Map.Entry<String, ViewManager> entry : mViewManagers.entrySet()) {
105-
entry.getValue().onSurfaceStopped(surfaceId);
109+
for (ViewManager viewManager : viewManagers) {
110+
viewManager.onSurfaceStopped(surfaceId);
106111
}
107112
}
108113
};
@@ -116,12 +121,16 @@ public void run() {
116121
/** ComponentCallbacks2 method. */
117122
@Override
118123
public void onTrimMemory(int level) {
124+
List<ViewManager> viewManagers;
125+
synchronized (this) {
126+
viewManagers = new ArrayList<>(mViewManagers.values());
127+
}
119128
Runnable runnable =
120129
new Runnable() {
121130
@Override
122131
public void run() {
123-
for (Map.Entry<String, ViewManager> entry : mViewManagers.entrySet()) {
124-
entry.getValue().trimMemory();
132+
for (ViewManager viewManager : viewManagers) {
133+
viewManager.trimMemory();
125134
}
126135
}
127136
};

0 commit comments

Comments
 (0)