Skip to content

Commit 3a5457c

Browse files
Dave MillerFacebook Github Bot 1
authored andcommitted
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
1 parent 3f0207d commit 3a5457c

6 files changed

Lines changed: 136 additions & 29 deletions

File tree

Libraries/Utilities/UIManager.js

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,6 @@
1414
var UIManager = require('NativeModules').UIManager;
1515
var findNodeHandle = require('findNodeHandle');
1616

17-
if (!UIManager.setChildren) {
18-
19-
/**
20-
* Index cache (used by setChildren())
21-
*/
22-
UIManager._cachedIndexArray = function(size) {
23-
var cachedResult = this._cachedIndexArray._cache[size];
24-
if (!cachedResult) {
25-
var arr = [];
26-
for (var i = 0; i < size; i++) {
27-
arr[i] = i;
28-
}
29-
this._cachedIndexArray._cache[size] = arr;
30-
return arr;
31-
} else {
32-
return cachedResult;
33-
}
34-
};
35-
UIManager._cachedIndexArray._cache = {};
36-
37-
/**
38-
* Fallback setChildren() implementation for Android
39-
*/
40-
UIManager.setChildren = function(containerTag, createdTags) {
41-
var indexes = this._cachedIndexArray(createdTags.length);
42-
UIManager.manageChildren(containerTag, null, null, createdTags, indexes, null);
43-
};
44-
}
45-
4617
const _takeSnapshot = UIManager.takeSnapshot;
4718

4819
/**

ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,51 @@ public void manageChildren(
388388
}
389389
}
390390

391+
/**
392+
* Simplified version of constructManageChildrenErrorMessage that only deals with adding children
393+
* views
394+
*/
395+
private static String constructSetChildrenErrorMessage(
396+
ViewGroup viewToManage,
397+
ViewGroupManager viewManager,
398+
ReadableArray childrenTags) {
399+
ViewAtIndex[] viewsToAdd = new ViewAtIndex[childrenTags.size()];
400+
for (int i = 0; i < childrenTags.size(); i++) {
401+
viewsToAdd[i] = new ViewAtIndex(childrenTags.getInt(i), i);
402+
}
403+
return constructManageChildrenErrorMessage(
404+
viewToManage,
405+
viewManager,
406+
null,
407+
viewsToAdd,
408+
null
409+
);
410+
}
411+
412+
/**
413+
* Simplified version of manageChildren that only deals with adding children views
414+
*/
415+
public void setChildren(
416+
int tag,
417+
ReadableArray childrenTags) {
418+
ViewGroup viewToManage = (ViewGroup) mTagsToViews.get(tag);
419+
ViewGroupManager viewManager = (ViewGroupManager) resolveViewManager(tag);
420+
421+
for (int i = 0; i < childrenTags.size(); i++) {
422+
View viewToAdd = mTagsToViews.get(childrenTags.getInt(i));
423+
if (viewToAdd == null) {
424+
throw new IllegalViewOperationException(
425+
"Trying to add unknown view tag: "
426+
+ childrenTags.getInt(i) + "\n detail: " +
427+
constructSetChildrenErrorMessage(
428+
viewToManage,
429+
viewManager,
430+
childrenTags));
431+
}
432+
viewManager.addView(viewToManage, viewToAdd, i);
433+
}
434+
}
435+
391436
/**
392437
* See {@link UIManagerModule#addMeasuredRootView}.
393438
*

ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyOptimizer.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import android.util.SparseBooleanArray;
1515

1616
import com.facebook.infer.annotation.Assertions;
17+
import com.facebook.react.bridge.ReadableArray;
1718
import com.facebook.react.bridge.ReadableMapKeySetIterator;
1819

1920
/**
@@ -171,6 +172,27 @@ public void handleManageChildren(
171172
}
172173
}
173174

175+
/**
176+
* Handles a setChildren call. This is a simplification of handleManagerChildren that only adds
177+
* children in index order of the childrenTags array
178+
*/
179+
public void handleSetChildren(
180+
ReactShadowNode nodeToManage,
181+
ReadableArray childrenTags
182+
) {
183+
if (!ENABLED) {
184+
mUIViewOperationQueue.enqueueSetChildren(
185+
nodeToManage.getReactTag(),
186+
childrenTags);
187+
return;
188+
}
189+
190+
for (int i = 0; i < childrenTags.size(); i++) {
191+
ReactShadowNode nodeToAdd = mShadowNodeRegistry.getNode(childrenTags.getInt(i));
192+
addNodeToNode(nodeToManage, nodeToAdd, i);
193+
}
194+
}
195+
174196
/**
175197
* Handles an updateLayout call. All updateLayout calls are collected and dispatched at the end
176198
* of a batch because updateLayout calls to layout-only nodes can necessitate multiple

ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,35 @@ public void manageChildren(
323323
}
324324
}
325325

326+
/**
327+
* An optimized version of manageChildren that is used for initial setting of child views.
328+
* The children are assumed to be in index order
329+
*
330+
* @param viewTag tag of the parent
331+
* @param childrenTags tags of the children
332+
*/
333+
public void setChildren(
334+
int viewTag,
335+
ReadableArray childrenTags) {
336+
337+
ReactShadowNode cssNodeToManage = mShadowNodeRegistry.getNode(viewTag);
338+
339+
for (int i = 0; i < childrenTags.size(); i++) {
340+
ReactShadowNode cssNodeToAdd = mShadowNodeRegistry.getNode(childrenTags.getInt(i));
341+
if (cssNodeToAdd == null) {
342+
throw new IllegalViewOperationException("Trying to add unknown view tag: "
343+
+ childrenTags.getInt(i));
344+
}
345+
cssNodeToManage.addChildAt(cssNodeToAdd, i);
346+
}
347+
348+
if (!cssNodeToManage.isVirtual() && !cssNodeToManage.isVirtualAnchor()) {
349+
mNativeViewHierarchyOptimizer.handleSetChildren(
350+
cssNodeToManage,
351+
childrenTags);
352+
}
353+
}
354+
326355
/**
327356
* Replaces the View specified by oldTag with the View specified by newTag within oldTag's parent.
328357
*/

ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,20 @@ public void manageChildren(
231231
removeFrom);
232232
}
233233

234+
/**
235+
* Interface for fast tracking the initial adding of views. Children view tags are assumed to be
236+
* in order
237+
*
238+
* @param viewTag the view tag of the parent view
239+
* @param childrenTags An array of tags to add to the parent in order
240+
*/
241+
@ReactMethod
242+
public void setChildren(
243+
int viewTag,
244+
ReadableArray childrenTags) {
245+
mUIImplementation.setChildren(viewTag, childrenTags);
246+
}
247+
234248
/**
235249
* Replaces the View specified by oldTag with the View specified by newTag within oldTag's parent.
236250
* This resolves to a simple {@link #manageChildren} call, but React doesn't have enough info in

ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,25 @@ public void execute() {
180180
}
181181
}
182182

183+
private final class SetChildrenOperation extends ViewOperation {
184+
185+
private final ReadableArray mChildrenTags;
186+
187+
public SetChildrenOperation(
188+
int tag,
189+
ReadableArray childrenTags) {
190+
super(tag);
191+
mChildrenTags = childrenTags;
192+
}
193+
194+
@Override
195+
public void execute() {
196+
mNativeViewHierarchyManager.setChildren(
197+
mTag,
198+
mChildrenTags);
199+
}
200+
}
201+
183202
private final class UpdateViewExtraData extends ViewOperation {
184203

185204
private final Object mExtraData;
@@ -640,6 +659,13 @@ public void enqueueManageChildren(
640659
new ManageChildrenOperation(reactTag, indicesToRemove, viewsToAdd, tagsToDelete));
641660
}
642661

662+
public void enqueueSetChildren(
663+
int reactTag,
664+
ReadableArray childrenTags) {
665+
mOperations.add(
666+
new SetChildrenOperation(reactTag, childrenTags));
667+
}
668+
643669
public void enqueueRegisterAnimation(Animation animation) {
644670
mOperations.add(new RegisterAnimationOperation(animation));
645671
}

0 commit comments

Comments
 (0)