Preallocate Image views

Summary:
This diff changes the pre-allocation of Images update the props on the ImageViews during the creation of ShadowNodes instead of during rendering.
The purpose of this change is to optimize TTI.

This was originally landed in D14214844 and then backed out in D14247897

Reviewed By: shergin

Differential Revision: D14286232

fbshipit-source-id: 8437f57f9473eb22ef98d80531b4020ee5fbb9ae
This commit is contained in:
David Vacca
2019-03-03 08:55:25 -08:00
committed by Facebook Github Bot
parent cf3653baac
commit aa69e51096
7 changed files with 39 additions and 17 deletions

View File

@@ -188,7 +188,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
}
@DoNotStrip
private void preallocateView(final int rootTag, final String componentName) {
private void preallocateView(int rootTag, int reactTag, final String componentName, ReadableMap props) {
if (UiThreadUtil.isOnUiThread()) {
// There is no reason to allocate views ahead of time on the main thread.
return;
@@ -198,7 +198,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
Assertions.assertNotNull(mReactContextForRootTag.get(rootTag));
String component = sComponentNames.get(componentName);
Assertions.assertNotNull(component);
mPreMountItems.add(new PreAllocateViewMountItem(context, rootTag, component));
mPreMountItems.add(new PreAllocateViewMountItem(context, rootTag, reactTag, component, props));
}
}

View File

@@ -461,16 +461,24 @@ void Binding::setPixelDensity(float pointScaleFactor) {
void Binding::schedulerDidRequestPreliminaryViewAllocation(
const SurfaceId surfaceId,
const ComponentName componentName,
bool isLayoutable,
const ComponentHandle componentHandle) {
const ShadowView &shadowView) {
if (isLayoutable) {
static auto preallocateView =
jni::findClassStatic(UIManagerJavaDescriptor)
->getMethod<void(jint, jstring)>("preallocateView");
->getMethod<void(jint, jint, jstring, ReadableMap::javaobject)>("preallocateView");
preallocateView(
javaUIManager_, surfaceId, make_jstring(componentName).get());
// TODO: T31905686 Experiment to check what is the impact on TTI of pre loading of Images during
// pre-allocation of views
if (shadowView.componentName == "Image") {
local_ref<ReadableMap::javaobject> readableMap =
castReadableMap(ReadableNativeMap::newObjectCxxArgs(shadowView.props->rawProps));
preallocateView(
javaUIManager_, surfaceId, shadowView.tag, make_jstring(shadowView.componentName).get(), readableMap.get());
} else {
preallocateView(
javaUIManager_, surfaceId, shadowView.tag, make_jstring(shadowView.componentName).get(), nullptr);
}
}
}

View File

@@ -64,9 +64,8 @@ class Binding : public jni::HybridClass<Binding>, public SchedulerDelegate {
void schedulerDidRequestPreliminaryViewAllocation(
const SurfaceId surfaceId,
const ComponentName componentName,
bool isLayoutable,
const ComponentHandle componentHandle);
const ShadowView &shadowView);
void setPixelDensity(float pointScaleFactor);

View File

@@ -172,6 +172,10 @@ public class MountingManager {
UiThreadUtil.assertOnUiThread();
View view = null;
ViewManager viewManager = null;
// This can be possible if the view was already pre-allocated
if (mTagToViewState.get(reactTag) != null) return;
if (!isVirtual) {
viewManager = mViewManagerRegistry.get(componentName);
view = mViewPool.getOrCreateView(componentName, themedReactContext);
@@ -271,8 +275,15 @@ public class MountingManager {
}
@UiThread
public void preallocateView(ThemedReactContext reactContext, String componentName) {
mViewPool.createView(reactContext, componentName);
public void preallocateView(
ThemedReactContext reactContext,
String componentName,
int reactTag,
ReadableMap props) {
createView(reactContext, componentName, reactTag, false);
if (props != null) {
updateProps(reactTag, props);
}
}
@UiThread

View File

@@ -6,6 +6,7 @@
*/
package com.facebook.react.fabric.mounting.mountitems;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.fabric.mounting.MountingManager;
import com.facebook.react.uimanager.ThemedReactContext;
@@ -16,17 +17,21 @@ public class PreAllocateViewMountItem implements MountItem {
private final String mComponent;
private final int mRootTag;
private final int mReactTag;
private final ReadableMap mProps;
private final ThemedReactContext mContext;
public PreAllocateViewMountItem(ThemedReactContext context, int rootTag, String component){
public PreAllocateViewMountItem(ThemedReactContext context, int rootTag, int reactTag, String component, ReadableMap props){
mContext = context;
mComponent = component;
mRootTag = rootTag;
mProps = props;
mReactTag = reactTag;
}
@Override
public void execute(MountingManager mountingManager) {
mountingManager.preallocateView(mContext, mComponent);
mountingManager.preallocateView(mContext, mComponent, mReactTag, mProps);
}
@Override

View File

@@ -259,11 +259,11 @@ void Scheduler::uiManagerDidCreateShadowNode(
dynamic_cast<const LayoutableShadowNode *>(shadowNode.get());
auto isLayoutable = layoutableShadowNode != nullptr;
auto shadowView = ShadowView(*shadowNode);
delegate_->schedulerDidRequestPreliminaryViewAllocation(
shadowNode->getRootTag(),
shadowNode->getComponentName(),
isLayoutable,
shadowNode->getComponentHandle());
shadowView);
}
}

View File

@@ -35,9 +35,8 @@ class SchedulerDelegate {
*/
virtual void schedulerDidRequestPreliminaryViewAllocation(
SurfaceId surfaceId,
ComponentName componentName,
bool isLayoutable,
ComponentHandle componentHandle) = 0;
const ShadowView &shadowView) = 0;
virtual ~SchedulerDelegate() noexcept = default;
};