diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java index f856e85d53..ab79b3f1ac 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagersPropertyCache.java @@ -45,13 +45,11 @@ import java.util.Map; protected final Method mSetter; protected final @Nullable Integer mIndex; /* non-null only for group setters */ - // The following Object arrays are used to prevent extra allocations from varargs when we call - // Method.invoke. It's safe for those objects to be static as we update properties in a single - // thread sequentially - private static final Object[] VIEW_MGR_ARGS = new Object[2]; - private static final Object[] VIEW_MGR_GROUP_ARGS = new Object[3]; - private static final Object[] SHADOW_ARGS = new Object[1]; - private static final Object[] SHADOW_GROUP_ARGS = new Object[2]; + // The following Object arrays are used to prevent extra allocations from varargs when we call. + private static final ThreadLocal VIEW_MGR_ARGS = createThreadLocalArray(2); + private static final ThreadLocal VIEW_MGR_GROUP_ARGS = createThreadLocalArray(3); + private static final ThreadLocal SHADOW_ARGS = createThreadLocalArray(1); + private static final ThreadLocal SHADOW_GROUP_ARGS = createThreadLocalArray(2); private PropSetter(ReactProp prop, String defaultType, Method setter) { mPropName = prop.name(); @@ -81,18 +79,19 @@ import java.util.Map; public void updateViewProp(ViewManager viewManager, View viewToUpdate, Object value) { try { + Object[] args; if (mIndex == null) { - VIEW_MGR_ARGS[0] = viewToUpdate; - VIEW_MGR_ARGS[1] = getValueOrDefault(value, viewToUpdate.getContext()); - mSetter.invoke(viewManager, VIEW_MGR_ARGS); - Arrays.fill(VIEW_MGR_ARGS, null); + args = VIEW_MGR_ARGS.get(); + args[0] = viewToUpdate; + args[1] = getValueOrDefault(value, viewToUpdate.getContext()); } else { - VIEW_MGR_GROUP_ARGS[0] = viewToUpdate; - VIEW_MGR_GROUP_ARGS[1] = mIndex; - VIEW_MGR_GROUP_ARGS[2] = getValueOrDefault(value, viewToUpdate.getContext()); - mSetter.invoke(viewManager, VIEW_MGR_GROUP_ARGS); - Arrays.fill(VIEW_MGR_GROUP_ARGS, null); + args = VIEW_MGR_GROUP_ARGS.get(); + args[0] = viewToUpdate; + args[1] = mIndex; + args[2] = getValueOrDefault(value, viewToUpdate.getContext()); } + mSetter.invoke(viewManager, args); + Arrays.fill(args, null); } catch (Throwable t) { FLog.e(ViewManager.class, "Error while updating prop " + mPropName, t); throw new JSApplicationIllegalArgumentException( @@ -106,16 +105,17 @@ import java.util.Map; public void updateShadowNodeProp(ReactShadowNode nodeToUpdate, Object value) { try { + Object[] args; if (mIndex == null) { - SHADOW_ARGS[0] = getValueOrDefault(value, nodeToUpdate.getThemedContext()); - mSetter.invoke(nodeToUpdate, SHADOW_ARGS); - Arrays.fill(SHADOW_ARGS, null); + args = SHADOW_ARGS.get(); + args[0] = getValueOrDefault(value, nodeToUpdate.getThemedContext()); } else { - SHADOW_GROUP_ARGS[0] = mIndex; - SHADOW_GROUP_ARGS[1] = getValueOrDefault(value, nodeToUpdate.getThemedContext()); - mSetter.invoke(nodeToUpdate, SHADOW_GROUP_ARGS); - Arrays.fill(SHADOW_GROUP_ARGS, null); + args = SHADOW_GROUP_ARGS.get(); + args[0] = mIndex; + args[1] = getValueOrDefault(value, nodeToUpdate.getThemedContext()); } + mSetter.invoke(nodeToUpdate, args); + Arrays.fill(args, null); } catch (Throwable t) { FLog.e(ViewManager.class, "Error while updating prop " + mPropName, t); throw new JSApplicationIllegalArgumentException( @@ -574,4 +574,19 @@ import java.util.Map; } } } + + private static ThreadLocal createThreadLocalArray(final int size) { + + if (size <= 0) { + return null; + } + + return new ThreadLocal() { + @Nullable + @Override + protected Object[] initialValue() { + return new Object[size]; + } + }; + } }