Always pass props and state to Create mount item

Summary: For Litho interop and to resolve T47926405, always pass props and state to Create mount item so that any ViewManager can create view instances with knowledge of initial props and state.

Reviewed By: mdvacca

Differential Revision: D16554082

fbshipit-source-id: 3b19a43347b0fa201a054eec60e82fb77cad3625
This commit is contained in:
Joshua Gross
2019-07-29 18:08:23 -07:00
committed by Facebook Github Bot
parent f22a7c67bd
commit bf5e73e46c
5 changed files with 56 additions and 10 deletions
@@ -219,7 +219,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
int reactTag,
final String componentName,
@Nullable ReadableMap props,
Object stateWrapper,
@Nullable Object stateWrapper,
boolean isLayoutable) {
ThemedReactContext context = mReactContextForRootTag.get(rootTag);
String component = getFabricComponentName(componentName);
@@ -239,13 +239,25 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@DoNotStrip
@SuppressWarnings("unused")
private MountItem createMountItem(
String componentName, int reactRootTag, int reactTag, boolean isLayoutable) {
String componentName,
@Nullable ReadableMap props,
@Nullable Object stateWrapper,
int reactRootTag,
int reactTag,
boolean isLayoutable) {
String component = getFabricComponentName(componentName);
ThemedReactContext reactContext = mReactContextForRootTag.get(reactRootTag);
if (reactContext == null) {
throw new IllegalArgumentException("Unable to find ReactContext for root: " + reactRootTag);
}
return new CreateMountItem(reactContext, reactRootTag, reactTag, component, isLayoutable);
return new CreateMountItem(
reactContext,
reactRootTag,
reactTag,
component,
props,
(StateWrapper) stateWrapper,
isLayoutable);
}
@DoNotStrip
@@ -449,6 +461,9 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
long batchedExecutionStartTime = SystemClock.uptimeMillis();
for (MountItem mountItem : mountItemsToDispatch) {
if (DEBUG) {
FLog.d(TAG, "dispatchMountItems: Executing mountItem: " + mountItem);
}
mountItem.execute(mMountingManager);
}
mBatchedExecutionTime = SystemClock.uptimeMillis() - batchedExecutionStartTime;
@@ -427,13 +427,15 @@ local_ref<JMountItem::javaobject> createDeleteMountItem(
return deleteInstruction(javaUIManager, mutation.oldChildShadowView.tag);
}
// TODO T48019320: because we pass initial props and state to the Create (and preallocate) mount instruction,
// we technically don't need to pass the first Update to any components. Dedupe?
local_ref<JMountItem::javaobject> createCreateMountItem(
const jni::global_ref<jobject> &javaUIManager,
const ShadowViewMutation &mutation,
const Tag surfaceId) {
static auto createJavaInstruction =
jni::findClassStatic(UIManagerJavaDescriptor)
->getMethod<alias_ref<JMountItem>(jstring, jint, jint, jboolean)>(
->getMethod<alias_ref<JMountItem>(jstring, ReadableMap::javaobject, jobject, jint, jint, jboolean)>(
"createMountItem");
auto newChildShadowView = mutation.newChildShadowView;
@@ -444,9 +446,24 @@ local_ref<JMountItem::javaobject> createCreateMountItem(
jboolean isLayoutable =
newChildShadowView.layoutMetrics != EmptyLayoutMetrics;
local_ref<ReadableMap::javaobject> props = castReadableMap(
ReadableNativeMap::newObjectCxxArgs(newChildShadowView.props->rawProps));
// Do not hold onto Java object from C
// We DO want to hold onto C object from Java, since we don't know the
// lifetime of the Java object
local_ref<StateWrapperImpl::JavaPart> javaStateWrapper = nullptr;
if (newChildShadowView.state != nullptr) {
javaStateWrapper = StateWrapperImpl::newObjectJavaArgs();
StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper);
cStateWrapper->state_ = newChildShadowView.state;
}
return createJavaInstruction(
javaUIManager,
componentName.get(),
props.get(),
(javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr),
surfaceId,
newChildShadowView.tag,
isLayoutable);
@@ -514,7 +531,7 @@ void Binding::schedulerDidFinishTransaction(
}
case ShadowViewMutation::Delete: {
mountItems[position++] =
createDeleteMountItem(localJavaUIManager, mutation);
createDeleteMountItem(localJavaUIManager, mutation);
deletedViewTags.insert(mutation.oldChildShadowView.tag);
break;
@@ -191,13 +191,11 @@ public class MountingManager {
if (isLayoutable) {
viewManager = mViewManagerRegistry.get(componentName);
// View Managers are responsible for dealing with initial state and props.
view =
mViewFactory.getOrCreateView(
componentName, propsDiffMap, stateWrapper, themedReactContext);
view.setId(reactTag);
if (stateWrapper != null) {
viewManager.updateState(view, propsDiffMap, stateWrapper);
}
}
ViewState viewState = new ViewState(reactTag, view, viewManager);
@@ -6,7 +6,10 @@
*/
package com.facebook.react.fabric.mounting.mountitems;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.fabric.mounting.MountingManager;
import com.facebook.react.uimanager.StateWrapper;
import com.facebook.react.uimanager.ThemedReactContext;
public class CreateMountItem implements MountItem {
@@ -15,6 +18,8 @@ public class CreateMountItem implements MountItem {
private final int mRootTag;
private final int mReactTag;
private final ThemedReactContext mContext;
private final @Nullable ReadableMap mProps;
private final @Nullable StateWrapper mStateWrapper;
private final boolean mIsLayoutable;
public CreateMountItem(
@@ -22,17 +27,22 @@ public class CreateMountItem implements MountItem {
int rootTag,
int reactTag,
String component,
@Nullable ReadableMap props,
StateWrapper stateWrapper,
boolean isLayoutable) {
mContext = context;
mComponent = component;
mRootTag = rootTag;
mReactTag = reactTag;
mProps = props;
mStateWrapper = stateWrapper;
mIsLayoutable = isLayoutable;
}
@Override
public void execute(MountingManager mountingManager) {
mountingManager.createView(mContext, mComponent, mReactTag, null, null, mIsLayoutable);
mountingManager.createView(
mContext, mComponent, mReactTag, mProps, mStateWrapper, mIsLayoutable);
}
@Override
@@ -117,6 +117,12 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
if (initialProps != null) {
updateProperties(view, initialProps);
}
if (stateWrapper != null) {
Object extraData = updateState(view, initialProps, stateWrapper);
if (extraData != null) {
updateExtraData(view, extraData);
}
}
return view;
}
@@ -150,7 +156,7 @@ public abstract class ViewManager<T extends View, C extends ReactShadowNode>
* x/y/width/height this is the recommended and thread-safe way of passing extra data from css
* node to the native view counterpart.
*
* <p>TODO(7247021): Replace updateExtraData with generic update props mechanism after D2086999
* <p>TODO T7247021: Replace updateExtraData with generic update props mechanism after D2086999
*/
public abstract void updateExtraData(@NonNull T root, Object extraData);