Optimize lookup of PlatformColor on Android

Summary:
We currently wrap colors in an object to make it look similar to a `PlatformColor` object, but since this is a hot codepath, let's just optimize it to a simple array of strings. The next step is to apply a layer of caching here, but this should be a simple improvement.

Changelog: [internal]

Reviewed By: JoshuaGross

Differential Revision: D31057046

fbshipit-source-id: f68e17167ddd5bba3b545d039600c7c9b40808f5
This commit is contained in:
Pieter De Baets
2022-06-10 16:20:22 -07:00
committed by Facebook GitHub Bot
parent 90cb8ea2a6
commit 34e51191e7
3 changed files with 47 additions and 47 deletions
@@ -10,6 +10,7 @@ package com.facebook.react.bridge;
import android.content.Context;
import android.content.res.Resources;
import android.util.TypedValue;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
public class ColorPropConverter {
@@ -44,27 +45,9 @@ public class ColorPropConverter {
}
for (int i = 0; i < resourcePaths.size(); i++) {
String resourcePath = resourcePaths.getString(i);
if (resourcePath == null || resourcePath.isEmpty()) {
continue;
}
boolean isResource = resourcePath.startsWith(PREFIX_RESOURCE);
boolean isThemeAttribute = resourcePath.startsWith(PREFIX_ATTR);
resourcePath = resourcePath.substring(1);
try {
if (isResource) {
return resolveResource(context, resourcePath);
} else if (isThemeAttribute) {
return resolveThemeAttribute(context, resourcePath);
}
} catch (Resources.NotFoundException exception) {
// The resource could not be found so do nothing to allow the for loop to continue and
// try the next fallback resource in the array. If none of the fallbacks are
// found then the exception immediately after the for loop will be thrown.
Integer result = resolveResourcePath(context, resourcePaths.getString(i));
if (result != null) {
return result;
}
}
@@ -78,6 +61,30 @@ public class ColorPropConverter {
"ColorValue: the value must be a number or Object.");
}
public static Integer resolveResourcePath(Context context, @Nullable String resourcePath) {
if (resourcePath == null || resourcePath.isEmpty()) {
return null;
}
boolean isResource = resourcePath.startsWith(PREFIX_RESOURCE);
boolean isThemeAttribute = resourcePath.startsWith(PREFIX_ATTR);
resourcePath = resourcePath.substring(1);
try {
if (isResource) {
return resolveResource(context, resourcePath);
} else if (isThemeAttribute) {
return resolveThemeAttribute(context, resourcePath);
}
} catch (Resources.NotFoundException exception) {
// The resource could not be found so do nothing to allow the for loop to continue and
// try the next fallback resource in the array. If none of the fallbacks are
// found then the exception immediately after the for loop will be thrown.
}
return null;
}
private static int resolveResource(Context context, String resourcePath) {
String[] pathTokens = resourcePath.split(PACKAGE_DELIMITER);
@@ -529,11 +529,16 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
}
@SuppressWarnings("unused")
public int getColor(int surfaceId, ReadableMap platformColor) {
public int getColor(int surfaceId, String[] resourcePaths) {
ThemedReactContext context =
mMountingManager.getSurfaceManagerEnforced(surfaceId, "getColor").getContext();
Integer color = ColorPropConverter.getColor(platformColor, context);
return color != null ? color : 0;
for (String resourcePath : resourcePaths) {
Integer color = ColorPropConverter.resolveResourcePath(context, resourcePath);
if (color != null) {
return color;
}
}
return 0;
}
@SuppressWarnings("unused")