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 коммит произвёл Facebook GitHub Bot
Родитель 90cb8ea2a6
Коммит 34e51191e7
3 изменённых файлов: 47 добавлений и 47 удалений

Просмотреть файл

@ -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")

Просмотреть файл

@ -22,35 +22,23 @@ inline ColorComponents parsePlatformColor(
ColorComponents colorComponents = {0, 0, 0, 0};
if (value.hasType<butter::map<std::string, std::vector<std::string>>>()) {
auto map = (butter::map<std::string, std::vector<std::string>>)value;
auto resourcePaths = map["resource_paths"];
auto dynamicResourcePaths = folly::dynamic::array();
for (const auto &resourcePath : resourcePaths) {
dynamicResourcePaths.push_back(resourcePath);
}
folly::dynamic dynamicPlatformColor = folly::dynamic::object();
dynamicPlatformColor["resource_paths"] = dynamicResourcePaths;
auto fabricUIManager =
const auto &fabricUIManager =
context.contextContainer.at<jni::global_ref<jobject>>(
"FabricUIManager");
static auto getColorFromJava =
facebook::jni::findClassStatic(
"com/facebook/react/fabric/FabricUIManager")
->getMethod<jint(jint, ReadableMap::javaobject)>("getColor");
fabricUIManager->getClass()
->getMethod<jint(jint, jni::JArrayClass<jni::JString>)>("getColor");
jni::local_ref<ReadableNativeMap::javaobject> dynamicPlatformColorRNM =
ReadableNativeMap::newObjectCxxArgs(dynamicPlatformColor);
jni::local_ref<ReadableMap::javaobject> dynamicPlatformColorRM =
jni::make_local(reinterpret_cast<ReadableMap::javaobject>(
dynamicPlatformColorRNM.get()));
auto map = (butter::map<std::string, std::vector<std::string>>)value;
auto &resourcePaths = map["resource_paths"];
auto javaResourcePaths =
jni::JArrayClass<jni::JString>::newArray(resourcePaths.size());
for (int i = 0; i < resourcePaths.size(); i++) {
javaResourcePaths->setElement(i, *jni::make_jstring(resourcePaths[i]));
}
auto color = getColorFromJava(
fabricUIManager, context.surfaceId, dynamicPlatformColorRM.get());
dynamicPlatformColorRM.reset();
dynamicPlatformColorRNM.reset();
fabricUIManager, context.surfaceId, *javaResourcePaths);
auto argb = (int64_t)color;
auto ratio = 255.f;