mirror of
https://github.com/status-im/react-native.git
synced 2025-01-14 03:26:07 +00:00
Android: Refactor HierarchyOptimizer in preparation of inline view support
Summary: This PR was split from commits originally in #8619. /cc dmmiller These refactorings to the HierarchyOptimizer are in preparation for implementing support for inline views in #8619. **Refactoring 1: Collapse add*LayoutOnlyNodeToLayoutOnlyNode** addLayoutOnlyNodeToLayoutOnlyNode and addNonLayoutOnlyNodeToLayoutOnlyNode had nearly identical implementations. They both walk thru the ancestors looking for a nonlayout-only node and adjusting the passed in index at each step. This introduces a new function, walkUpUntilNonLayoutOnly, which takes care of that responsibility. This simplifies addNodeToNode because it can now consider the type of the parent and the type of the child independently. **Refactoring 2: Extract addGrandchildren** Pull out addLayoutOnlyNode's logic into a helper called addGrandchildren. We will need to call this method in another place later. **Test plan (required)** This change was tested with UIExplorer and a small test app and it's being used in my team's app. Closes https://github.com/facebook/react-native/pull/8908 Differential Revision: D3592783 Pulled By: dmmiller fbshipit-source-id: a513e8d381e71112ce6348bbee7d4a7c62c33619
This commit is contained in:
parent
0587c85094
commit
e1b3bbdb04
@ -52,6 +52,16 @@ import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||
*/
|
||||
public class NativeViewHierarchyOptimizer {
|
||||
|
||||
private static class NodeIndexPair {
|
||||
public final ReactShadowNode node;
|
||||
public final int index;
|
||||
|
||||
NodeIndexPair(ReactShadowNode node, int index) {
|
||||
this.node = node;
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean ENABLED = true;
|
||||
|
||||
private final UIViewOperationQueue mUIViewOperationQueue;
|
||||
@ -221,21 +231,39 @@ public class NativeViewHierarchyOptimizer {
|
||||
mTagsWithLayoutVisited.clear();
|
||||
}
|
||||
|
||||
private NodeIndexPair walkUpUntilNonLayoutOnly(
|
||||
ReactShadowNode node,
|
||||
int indexInNativeChildren) {
|
||||
while (node.isLayoutOnly()) {
|
||||
ReactShadowNode parent = node.getParent();
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
indexInNativeChildren = indexInNativeChildren + parent.getNativeOffsetForChild(node);
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return new NodeIndexPair(node, indexInNativeChildren);
|
||||
}
|
||||
|
||||
private void addNodeToNode(ReactShadowNode parent, ReactShadowNode child, int index) {
|
||||
int indexInNativeChildren = parent.getNativeOffsetForChild(parent.getChildAt(index));
|
||||
boolean parentIsLayoutOnly = parent.isLayoutOnly();
|
||||
boolean childIsLayoutOnly = child.isLayoutOnly();
|
||||
if (parent.isLayoutOnly()) {
|
||||
NodeIndexPair result = walkUpUntilNonLayoutOnly(parent, indexInNativeChildren);
|
||||
if (result == null) {
|
||||
// If the parent hasn't been attached to its native parent yet, don't issue commands to the
|
||||
// native hierarchy. We'll do that when the parent node actually gets attached somewhere.
|
||||
return;
|
||||
}
|
||||
parent = result.node;
|
||||
indexInNativeChildren = result.index;
|
||||
}
|
||||
|
||||
// Switch on the four cases of:
|
||||
// add (layout-only|not layout-only) to (layout-only|not layout-only)
|
||||
if (!parentIsLayoutOnly && !childIsLayoutOnly) {
|
||||
addNonLayoutNodeToNonLayoutNode(parent, child, indexInNativeChildren);
|
||||
} else if (!childIsLayoutOnly) {
|
||||
addNonLayoutOnlyNodeToLayoutOnlyNode(parent, child, indexInNativeChildren);
|
||||
} else if (!parentIsLayoutOnly) {
|
||||
addLayoutOnlyNodeToNonLayoutOnlyNode(parent, child, indexInNativeChildren);
|
||||
if (!child.isLayoutOnly()) {
|
||||
addNonLayoutNode(parent, child, indexInNativeChildren);
|
||||
} else {
|
||||
addLayoutOnlyNodeToLayoutOnlyNode(parent, child, indexInNativeChildren);
|
||||
addLayoutOnlyNode(parent, child, indexInNativeChildren);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,73 +290,14 @@ public class NativeViewHierarchyOptimizer {
|
||||
}
|
||||
}
|
||||
|
||||
private void addLayoutOnlyNodeToLayoutOnlyNode(
|
||||
ReactShadowNode parent,
|
||||
ReactShadowNode child,
|
||||
int index) {
|
||||
ReactShadowNode parentParent = parent.getParent();
|
||||
|
||||
// If the parent hasn't been attached to its parent yet, don't issue commands to the native
|
||||
// hierarchy. We'll do that when the parent node actually gets attached somewhere.
|
||||
if (parentParent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int transformedIndex = index + parentParent.getNativeOffsetForChild(parent);
|
||||
if (parentParent.isLayoutOnly()) {
|
||||
addLayoutOnlyNodeToLayoutOnlyNode(parentParent, child, transformedIndex);
|
||||
} else {
|
||||
addLayoutOnlyNodeToNonLayoutOnlyNode(parentParent, child, transformedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void addNonLayoutOnlyNodeToLayoutOnlyNode(
|
||||
ReactShadowNode layoutOnlyNode,
|
||||
ReactShadowNode nonLayoutOnlyNode,
|
||||
int index) {
|
||||
ReactShadowNode parent = layoutOnlyNode.getParent();
|
||||
|
||||
// If the parent hasn't been attached to its parent yet, don't issue commands to the native
|
||||
// hierarchy. We'll do that when the parent node actually gets attached somewhere.
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int transformedIndex = index + parent.getNativeOffsetForChild(layoutOnlyNode);
|
||||
if (parent.isLayoutOnly()) {
|
||||
addNonLayoutOnlyNodeToLayoutOnlyNode(parent, nonLayoutOnlyNode, transformedIndex);
|
||||
} else {
|
||||
addNonLayoutNodeToNonLayoutNode(parent, nonLayoutOnlyNode, transformedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void addLayoutOnlyNodeToNonLayoutOnlyNode(
|
||||
private void addLayoutOnlyNode(
|
||||
ReactShadowNode nonLayoutOnlyNode,
|
||||
ReactShadowNode layoutOnlyNode,
|
||||
int index) {
|
||||
// Add all of the layout-only node's children to its parent instead
|
||||
int currentIndex = index;
|
||||
for (int i = 0; i < layoutOnlyNode.getChildCount(); i++) {
|
||||
ReactShadowNode childToAdd = layoutOnlyNode.getChildAt(i);
|
||||
Assertions.assertCondition(childToAdd.getNativeParent() == null);
|
||||
|
||||
if (childToAdd.isLayoutOnly()) {
|
||||
// Adding this layout-only child could result in adding multiple native views
|
||||
int childCountBefore = nonLayoutOnlyNode.getNativeChildCount();
|
||||
addLayoutOnlyNodeToNonLayoutOnlyNode(
|
||||
nonLayoutOnlyNode,
|
||||
childToAdd,
|
||||
currentIndex);
|
||||
int childCountAfter = nonLayoutOnlyNode.getNativeChildCount();
|
||||
currentIndex += childCountAfter - childCountBefore;
|
||||
} else {
|
||||
addNonLayoutNodeToNonLayoutNode(nonLayoutOnlyNode, childToAdd, currentIndex);
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
addGrandchildren(nonLayoutOnlyNode, layoutOnlyNode, index);
|
||||
}
|
||||
|
||||
private void addNonLayoutNodeToNonLayoutNode(
|
||||
private void addNonLayoutNode(
|
||||
ReactShadowNode parent,
|
||||
ReactShadowNode child,
|
||||
int index) {
|
||||
@ -340,6 +309,31 @@ public class NativeViewHierarchyOptimizer {
|
||||
null);
|
||||
}
|
||||
|
||||
private void addGrandchildren(
|
||||
ReactShadowNode nativeParent,
|
||||
ReactShadowNode child,
|
||||
int index) {
|
||||
Assertions.assertCondition(!nativeParent.isLayoutOnly());
|
||||
|
||||
// `child` can't hold native children. Add all of `child`'s children to `parent`.
|
||||
int currentIndex = index;
|
||||
for (int i = 0; i < child.getChildCount(); i++) {
|
||||
ReactShadowNode grandchild = child.getChildAt(i);
|
||||
Assertions.assertCondition(grandchild.getNativeParent() == null);
|
||||
|
||||
if (grandchild.isLayoutOnly()) {
|
||||
// Adding this child could result in adding multiple native views
|
||||
int grandchildCountBefore = nativeParent.getNativeChildCount();
|
||||
addLayoutOnlyNode(nativeParent, grandchild, currentIndex);
|
||||
int grandchildCountAfter = nativeParent.getNativeChildCount();
|
||||
currentIndex += grandchildCountAfter - grandchildCountBefore;
|
||||
} else {
|
||||
addNonLayoutNode(nativeParent, grandchild, currentIndex);
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyLayoutBase(ReactShadowNode node) {
|
||||
int tag = node.getReactTag();
|
||||
if (mTagsWithLayoutVisited.get(tag)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user