Store \"dirty\" and \"dirty descendant\" flags in every node instead of only marking root node as invalid
Summary: Right now invalidate always tell the root node that the tree is dirty, and next update will traverse the entire tree in search of changes. While this works correctly, it's not the most efficient implementation. It is more efficient to store dirty flag in every node, and skip entire subtrees if this node and all descendants are already up to date. This diff is a first step towards that optimization. Reviewed By: ahmedre Differential Revision: D2955197
This commit is contained in:
parent
4c92a0b962
commit
ca7a3519cf
|
@ -19,8 +19,6 @@ package com.facebook.react.flat;
|
|||
signalBackingViewIsCreated();
|
||||
}
|
||||
|
||||
private boolean mIsUpdated;
|
||||
|
||||
/**
|
||||
* Returns true when this CSSNode tree needs to be re-laid out. If true, FlatUIImplementation
|
||||
* will request LayoutEngine to perform a layout pass to update node boundaries. This is used
|
||||
|
@ -29,19 +27,4 @@ package com.facebook.react.flat;
|
|||
/* package */ boolean needsLayout() {
|
||||
return isDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are updates to the node tree other than layout (such as a change in
|
||||
* background color) that would require StateBuilder to re-collect drawing state.
|
||||
*/
|
||||
/* package */ boolean isUpdated() {
|
||||
return mIsUpdated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the node tree as requiring or not requiring a StateBuilder pass to collect drawing state.
|
||||
*/
|
||||
/* package */ void markUpdated(boolean isUpdated) {
|
||||
mIsUpdated = isUpdated;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import javax.annotation.Nullable;
|
|||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.OnLayoutEvent;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
@ -50,6 +51,7 @@ import com.facebook.react.uimanager.annotations.ReactProp;
|
|||
private @Nullable DrawBackgroundColor mDrawBackground;
|
||||
private int mMoveToIndexInParent;
|
||||
private boolean mClipToBounds = false;
|
||||
private boolean mIsUpdated = true;
|
||||
|
||||
// last OnLayoutEvent info, only used when shouldNotifyOnLayout() is true.
|
||||
private int mLayoutX;
|
||||
|
@ -142,7 +144,34 @@ import com.facebook.react.uimanager.annotations.ReactProp;
|
|||
* color is changed).
|
||||
*/
|
||||
protected final void invalidate() {
|
||||
((FlatRootShadowNode) getRootNode()).markUpdated(true);
|
||||
FlatShadowNode node = this;
|
||||
|
||||
while (true) {
|
||||
if (node.mountsToView()) {
|
||||
if (node.mIsUpdated) {
|
||||
// already updated
|
||||
return;
|
||||
}
|
||||
|
||||
node.mIsUpdated = true;
|
||||
}
|
||||
|
||||
ReactShadowNode parent = node.getParent();
|
||||
if (parent == null) {
|
||||
// not attached to a hierarchy yet
|
||||
return;
|
||||
}
|
||||
|
||||
node = (FlatShadowNode) parent;
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ final boolean isUpdated() {
|
||||
return mIsUpdated;
|
||||
}
|
||||
|
||||
/* package */ final void resetUpdated() {
|
||||
mIsUpdated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -267,9 +296,7 @@ import com.facebook.react.uimanager.annotations.ReactProp;
|
|||
|
||||
if (mDrawView == null) {
|
||||
mDrawView = DrawView.INSTANCE;
|
||||
if (getParent() != null) {
|
||||
invalidate();
|
||||
}
|
||||
invalidate();
|
||||
|
||||
// reset NodeRegion to allow it getting garbage-collected
|
||||
mNodeRegion = NodeRegion.EMPTY;
|
||||
|
|
|
@ -418,7 +418,6 @@ public class FlatUIImplementation extends UIImplementation {
|
|||
}
|
||||
|
||||
super.calculateRootLayout(rootNode);
|
||||
rootNode.markUpdated(false);
|
||||
mStateBuilder.applyUpdates(eventDispatcher, rootNode);
|
||||
}
|
||||
|
||||
|
|
|
@ -447,6 +447,8 @@ import com.facebook.react.uimanager.events.EventDispatcher;
|
|||
isAndroidView,
|
||||
needsCustomLayoutForChildren);
|
||||
}
|
||||
|
||||
node.resetUpdated();
|
||||
}
|
||||
|
||||
private void markLayoutSeenRecursively(ReactShadowNode node) {
|
||||
|
|
Loading…
Reference in New Issue