Used hasDirtyChildren tag for the optimization
Reviewed By: emilsjolander Differential Revision: D6134754 fbshipit-source-id: bbcfee14058140b946401de756a3f130de0f51cd
This commit is contained in:
Родитель
387a3557ae
Коммит
587225ab45
|
@ -82,6 +82,8 @@ public interface ReactShadowNode<T extends ReactShadowNode> {
|
|||
|
||||
boolean isDirty();
|
||||
|
||||
boolean hasDirtyDescendants();
|
||||
|
||||
void addChildAt(T child, int i);
|
||||
|
||||
T removeChildAt(int i);
|
||||
|
|
|
@ -134,7 +134,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode<ReactShadowNodeImpl>
|
|||
|
||||
@Override
|
||||
public final boolean hasUpdates() {
|
||||
return mNodeUpdated || hasNewLayout() || isDirty();
|
||||
return mNodeUpdated || hasNewLayout() || isDirty() || hasDirtyDescendants();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -174,6 +174,11 @@ public class ReactShadowNodeImpl implements ReactShadowNode<ReactShadowNodeImpl>
|
|||
return mYogaNode != null && mYogaNode.isDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDirtyDescendants() {
|
||||
return mYogaNode != null && mYogaNode.hasDirtyDescendants();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChildAt(ReactShadowNodeImpl child, int i) {
|
||||
if (child.getParent() != null) {
|
||||
|
|
|
@ -9,13 +9,11 @@
|
|||
|
||||
package com.facebook.yoga;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@DoNotStrip
|
||||
public class YogaNode {
|
||||
|
@ -198,6 +196,12 @@ public class YogaNode {
|
|||
return jni_YGNodeIsDirty(mNativePointer);
|
||||
}
|
||||
|
||||
private native boolean jni_YGNodeHasDirtyDescendants(long nativePointer);
|
||||
|
||||
public boolean hasDirtyDescendants() {
|
||||
return jni_YGNodeHasDirtyDescendants(mNativePointer);
|
||||
}
|
||||
|
||||
private native void jni_YGNodeCopyStyle(long dstNativePointer, long srcNativePointer);
|
||||
public void copyStyle(YogaNode srcNode) {
|
||||
jni_YGNodeCopyStyle(mNativePointer, srcNode.mNativePointer);
|
||||
|
|
|
@ -249,6 +249,10 @@ jboolean jni_YGNodeIsDirty(alias_ref<jobject>, jlong nativePointer) {
|
|||
return (jboolean) YGNodeIsDirty(_jlong2YGNodeRef(nativePointer));
|
||||
}
|
||||
|
||||
jboolean jni_YGNodeHasDirtyDescendants(alias_ref<jobject>, jlong nativePointer) {
|
||||
return (jboolean) YGNodeHasDirtyDescendants(_jlong2YGNodeRef(nativePointer));
|
||||
}
|
||||
|
||||
void jni_YGNodeSetHasMeasureFunc(alias_ref<jobject>, jlong nativePointer, jboolean hasMeasureFunc) {
|
||||
YGNodeSetMeasureFunc(_jlong2YGNodeRef(nativePointer), hasMeasureFunc ? YGJNIMeasureFunc : NULL);
|
||||
}
|
||||
|
@ -422,9 +426,7 @@ void jni_YGConfigSetLogger(alias_ref<jobject>, jlong nativePointer, alias_ref<jo
|
|||
|
||||
auto context = YGConfigGetContext(config);
|
||||
if (context) {
|
||||
auto jlogger = reinterpret_cast<global_ref<jobject> *>(context);
|
||||
jlogger->releaseAlias();
|
||||
delete jlogger;
|
||||
delete reinterpret_cast<global_ref<jobject> *>(context);
|
||||
}
|
||||
|
||||
if (logger) {
|
||||
|
@ -455,6 +457,7 @@ jint JNI_OnLoad(JavaVM *vm, void *) {
|
|||
YGMakeNativeMethod(jni_YGNodeCalculateLayout),
|
||||
YGMakeNativeMethod(jni_YGNodeMarkDirty),
|
||||
YGMakeNativeMethod(jni_YGNodeIsDirty),
|
||||
YGMakeNativeMethod(jni_YGNodeHasDirtyDescendants),
|
||||
YGMakeNativeMethod(jni_YGNodeSetHasMeasureFunc),
|
||||
YGMakeNativeMethod(jni_YGNodeSetHasBaselineFunc),
|
||||
YGMakeNativeMethod(jni_YGNodeCopyStyle),
|
||||
|
|
|
@ -123,6 +123,7 @@ typedef struct YGNode {
|
|||
void *context;
|
||||
|
||||
bool isDirty;
|
||||
bool hasDirtyDescendants;
|
||||
bool hasNewLayout;
|
||||
YGNodeType nodeType;
|
||||
|
||||
|
@ -162,6 +163,7 @@ static const YGNode gYGNodeDefaults = {
|
|||
.children = NULL,
|
||||
.hasNewLayout = true,
|
||||
.isDirty = false,
|
||||
.hasDirtyDescendants = false,
|
||||
.nodeType = YGNodeTypeDefault,
|
||||
.resolvedDimensions = {[YGDimensionWidth] = &YGValueUndefined,
|
||||
[YGDimensionHeight] = &YGValueUndefined},
|
||||
|
@ -238,6 +240,8 @@ static YGConfig gYGConfigDefaults = {
|
|||
};
|
||||
|
||||
static void YGNodeMarkDirtyInternal(const YGNodeRef node);
|
||||
static bool YGNodeIsLayoutBoundary(const YGNodeRef node);
|
||||
static void YGNodeMarkHasDirtyDescendants(const YGNodeRef node);
|
||||
|
||||
YGMalloc gYGMalloc = &malloc;
|
||||
YGCalloc gYGCalloc = &calloc;
|
||||
|
@ -452,16 +456,33 @@ void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) {
|
|||
memcpy(dest, src, sizeof(YGConfig));
|
||||
}
|
||||
|
||||
static void YGNodeMarkHasDirtyDescendants(const YGNodeRef node) {
|
||||
if (node && !node->hasDirtyDescendants) {
|
||||
node->hasDirtyDescendants = true;
|
||||
YGNodeMarkHasDirtyDescendants(node->parent);
|
||||
}
|
||||
}
|
||||
|
||||
static void YGNodeMarkDirtyInternal(const YGNodeRef node) {
|
||||
if (!node->isDirty) {
|
||||
node->isDirty = true;
|
||||
node->layout.computedFlexBasis = YGUndefined;
|
||||
if (node->parent) {
|
||||
YGNodeMarkDirtyInternal(node->parent);
|
||||
if (YGNodeIsLayoutBoundary(node->parent)) {
|
||||
node->parent->isDirty = true; // Because parent lays out the child
|
||||
node->parent->layout.computedFlexBasis = YGUndefined;
|
||||
YGNodeMarkHasDirtyDescendants(node->parent);
|
||||
} else {
|
||||
YGNodeMarkDirtyInternal(node->parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool YGNodeIsLayoutBoundary(const YGNodeRef node) {
|
||||
return YGNodeStyleGetPositionType(node) == YGPositionTypeAbsolute;
|
||||
}
|
||||
|
||||
void YGNodeSetMeasureFunc(const YGNodeRef node, YGMeasureFunc measureFunc) {
|
||||
if (measureFunc == NULL) {
|
||||
node->measure = NULL;
|
||||
|
@ -628,6 +649,10 @@ bool YGNodeIsDirty(const YGNodeRef node) {
|
|||
return node->isDirty;
|
||||
}
|
||||
|
||||
bool YGNodeHasDirtyDescendants(const YGNodeRef node) {
|
||||
return node->hasDirtyDescendants;
|
||||
}
|
||||
|
||||
void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode) {
|
||||
if (memcmp(&dstNode->style, &srcNode->style, sizeof(YGStyle)) != 0) {
|
||||
memcpy(&dstNode->style, &srcNode->style, sizeof(YGStyle));
|
||||
|
@ -3406,7 +3431,6 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
|||
const char *reason,
|
||||
const YGConfigRef config) {
|
||||
YGLayout *layout = &node->layout;
|
||||
|
||||
gDepth++;
|
||||
|
||||
const bool needToVisitNode =
|
||||
|
@ -3498,6 +3522,26 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
|||
if (!needToVisitNode && cachedResults != NULL) {
|
||||
layout->measuredDimensions[YGDimensionWidth] = cachedResults->computedWidth;
|
||||
layout->measuredDimensions[YGDimensionHeight] = cachedResults->computedHeight;
|
||||
if (YGNodeHasDirtyDescendants(node)) {
|
||||
const uint32_t childCount = YGNodeListCount(node->children);
|
||||
for (uint32_t i = 0; i < childCount; ++i) {
|
||||
const YGNodeRef child = YGNodeListGet(node->children, i);
|
||||
if (child->isDirty || YGNodeHasDirtyDescendants(child)) {
|
||||
YGLayoutNodeInternal(child,
|
||||
child->layout.cachedLayout.availableWidth,
|
||||
child->layout.cachedLayout.availableHeight,
|
||||
child->layout.direction,
|
||||
child->layout.cachedLayout.widthMeasureMode,
|
||||
child->layout.cachedLayout.heightMeasureMode,
|
||||
cachedResults->computedWidth,
|
||||
cachedResults->computedHeight,
|
||||
performLayout,
|
||||
"layout",
|
||||
child->config
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gPrintChanges && gPrintSkips) {
|
||||
printf("%s%d.{[skipped] ", YGSpacer(gDepth), gDepth);
|
||||
|
@ -3585,6 +3629,7 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
|||
node->layout.dimensions[YGDimensionHeight] = node->layout.measuredDimensions[YGDimensionHeight];
|
||||
node->hasNewLayout = true;
|
||||
node->isDirty = false;
|
||||
node->hasDirtyDescendants = false;
|
||||
}
|
||||
|
||||
gDepth--;
|
||||
|
|
|
@ -101,6 +101,7 @@ WIN_EXPORT void YGNodeCalculateLayout(const YGNodeRef node,
|
|||
// marking manually.
|
||||
WIN_EXPORT void YGNodeMarkDirty(const YGNodeRef node);
|
||||
WIN_EXPORT bool YGNodeIsDirty(const YGNodeRef node);
|
||||
WIN_EXPORT bool YGNodeHasDirtyDescendants(const YGNodeRef node);
|
||||
|
||||
WIN_EXPORT void YGNodePrint(const YGNodeRef node, const YGPrintOptions options);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче