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:
Denis Koroskin
2016-02-25 11:10:56 -08:00
committed by Ahmed El-Helw
parent 4c92a0b962
commit ca7a3519cf
4 changed files with 33 additions and 22 deletions

View File

@@ -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;