Add support for setChildren

Summary: This adds support for UIManager.setChildren on Android like D2757388 added for iOS.

Reviewed By: andreicoman11

Differential Revision: D3235369

fb-gh-sync-id: b538556ec4abdb606f9be26d1b74734046bca0cd
fbshipit-source-id: b538556ec4abdb606f9be26d1b74734046bca0cd
This commit is contained in:
Dave Miller
2016-04-29 04:02:22 -07:00
committed by Facebook Github Bot 1
parent 3f0207d7b5
commit 3a5457cd7c
6 changed files with 136 additions and 29 deletions

View File

@@ -388,6 +388,51 @@ public class NativeViewHierarchyManager {
}
}
/**
* Simplified version of constructManageChildrenErrorMessage that only deals with adding children
* views
*/
private static String constructSetChildrenErrorMessage(
ViewGroup viewToManage,
ViewGroupManager viewManager,
ReadableArray childrenTags) {
ViewAtIndex[] viewsToAdd = new ViewAtIndex[childrenTags.size()];
for (int i = 0; i < childrenTags.size(); i++) {
viewsToAdd[i] = new ViewAtIndex(childrenTags.getInt(i), i);
}
return constructManageChildrenErrorMessage(
viewToManage,
viewManager,
null,
viewsToAdd,
null
);
}
/**
* Simplified version of manageChildren that only deals with adding children views
*/
public void setChildren(
int tag,
ReadableArray childrenTags) {
ViewGroup viewToManage = (ViewGroup) mTagsToViews.get(tag);
ViewGroupManager viewManager = (ViewGroupManager) resolveViewManager(tag);
for (int i = 0; i < childrenTags.size(); i++) {
View viewToAdd = mTagsToViews.get(childrenTags.getInt(i));
if (viewToAdd == null) {
throw new IllegalViewOperationException(
"Trying to add unknown view tag: "
+ childrenTags.getInt(i) + "\n detail: " +
constructSetChildrenErrorMessage(
viewToManage,
viewManager,
childrenTags));
}
viewManager.addView(viewToManage, viewToAdd, i);
}
}
/**
* See {@link UIManagerModule#addMeasuredRootView}.
*

View File

@@ -14,6 +14,7 @@ import javax.annotation.Nullable;
import android.util.SparseBooleanArray;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
/**
@@ -171,6 +172,27 @@ public class NativeViewHierarchyOptimizer {
}
}
/**
* Handles a setChildren call. This is a simplification of handleManagerChildren that only adds
* children in index order of the childrenTags array
*/
public void handleSetChildren(
ReactShadowNode nodeToManage,
ReadableArray childrenTags
) {
if (!ENABLED) {
mUIViewOperationQueue.enqueueSetChildren(
nodeToManage.getReactTag(),
childrenTags);
return;
}
for (int i = 0; i < childrenTags.size(); i++) {
ReactShadowNode nodeToAdd = mShadowNodeRegistry.getNode(childrenTags.getInt(i));
addNodeToNode(nodeToManage, nodeToAdd, i);
}
}
/**
* Handles an updateLayout call. All updateLayout calls are collected and dispatched at the end
* of a batch because updateLayout calls to layout-only nodes can necessitate multiple

View File

@@ -323,6 +323,35 @@ public class UIImplementation {
}
}
/**
* An optimized version of manageChildren that is used for initial setting of child views.
* The children are assumed to be in index order
*
* @param viewTag tag of the parent
* @param childrenTags tags of the children
*/
public void setChildren(
int viewTag,
ReadableArray childrenTags) {
ReactShadowNode cssNodeToManage = mShadowNodeRegistry.getNode(viewTag);
for (int i = 0; i < childrenTags.size(); i++) {
ReactShadowNode cssNodeToAdd = mShadowNodeRegistry.getNode(childrenTags.getInt(i));
if (cssNodeToAdd == null) {
throw new IllegalViewOperationException("Trying to add unknown view tag: "
+ childrenTags.getInt(i));
}
cssNodeToManage.addChildAt(cssNodeToAdd, i);
}
if (!cssNodeToManage.isVirtual() && !cssNodeToManage.isVirtualAnchor()) {
mNativeViewHierarchyOptimizer.handleSetChildren(
cssNodeToManage,
childrenTags);
}
}
/**
* Replaces the View specified by oldTag with the View specified by newTag within oldTag's parent.
*/

View File

@@ -231,6 +231,20 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
removeFrom);
}
/**
* Interface for fast tracking the initial adding of views. Children view tags are assumed to be
* in order
*
* @param viewTag the view tag of the parent view
* @param childrenTags An array of tags to add to the parent in order
*/
@ReactMethod
public void setChildren(
int viewTag,
ReadableArray childrenTags) {
mUIImplementation.setChildren(viewTag, childrenTags);
}
/**
* Replaces the View specified by oldTag with the View specified by newTag within oldTag's parent.
* This resolves to a simple {@link #manageChildren} call, but React doesn't have enough info in

View File

@@ -180,6 +180,25 @@ public class UIViewOperationQueue {
}
}
private final class SetChildrenOperation extends ViewOperation {
private final ReadableArray mChildrenTags;
public SetChildrenOperation(
int tag,
ReadableArray childrenTags) {
super(tag);
mChildrenTags = childrenTags;
}
@Override
public void execute() {
mNativeViewHierarchyManager.setChildren(
mTag,
mChildrenTags);
}
}
private final class UpdateViewExtraData extends ViewOperation {
private final Object mExtraData;
@@ -640,6 +659,13 @@ public class UIViewOperationQueue {
new ManageChildrenOperation(reactTag, indicesToRemove, viewsToAdd, tagsToDelete));
}
public void enqueueSetChildren(
int reactTag,
ReadableArray childrenTags) {
mOperations.add(
new SetChildrenOperation(reactTag, childrenTags));
}
public void enqueueRegisterAnimation(Animation animation) {
mOperations.add(new RegisterAnimationOperation(animation));
}