diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view.cpp index 95e5898bf77365f7e22027141c398224c91ef9f5..6791d75c8115ae58db83c408f297d62208029af8 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view.cpp @@ -978,6 +978,11 @@ void JSViewPartialUpdate::MarkNeedUpdate() needsUpdate_ = ViewPartialUpdateModel::GetInstance()->MarkNeedUpdate(viewNode_); } +void JSViewPartialUpdate::RemoveFromDirtyList() +{ + ViewPartialUpdateModel::GetInstance()->RemoveFromDirtyList(viewNode_); +} + /** * in JS View.create(new View(...)); * used for FullRender case, not for re-render case @@ -1278,6 +1283,7 @@ void JSViewPartialUpdate::JSBind(BindingTarget object) JSClass::StaticMethod("create", &JSViewPartialUpdate::Create, opt); JSClass::StaticMethod("createRecycle", &JSViewPartialUpdate::CreateRecycle, opt); JSClass::Method("markNeedUpdate", &JSViewPartialUpdate::MarkNeedUpdate); + JSClass::Method("removeFromDirtyList", &JSViewPartialUpdate::RemoveFromDirtyList); JSClass::Method("syncInstanceId", &JSViewPartialUpdate::SyncInstanceId); JSClass::Method("restoreInstanceId", &JSViewPartialUpdate::RestoreInstanceId); JSClass::CustomMethod("getInstanceId", &JSViewPartialUpdate::GetInstanceId); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view.h b/frameworks/bridge/declarative_frontend/jsview/js_view.h index 5570092061c503f1679f2934024509734af9be95..48e4151493bba9c4e2b26446de3aeffb7c963148 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_view.h @@ -455,6 +455,8 @@ public: private: void MarkNeedUpdate() override; + void RemoveFromDirtyList(); + // indicates if the JSView has ever completed initial render // used for code branching in lambda given to ComposedComponent // render callback diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts index b39ddf54fb6212211a22eb3c04bc09182c63c798..4eb6b551459bf41b7d24a891769c136fd6ec4e2c 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts @@ -140,6 +140,10 @@ abstract class PUV2ViewBase extends ViewBuildNodeBase { public markNeedUpdate(): void { return this.nativeViewPartialUpdate.markNeedUpdate(); } + + public removeFromDirtyList(): void { + return this.nativeViewPartialUpdate.removeFromDirtyList(); + } public syncInstanceId(): void { return this.nativeViewPartialUpdate.syncInstanceId(); @@ -402,7 +406,10 @@ abstract class PUV2ViewBase extends ViewBuildNodeBase { ObserveV2.getObserve()?.runIdleTasks(); // to avoid to run the update func twice // it is not necessary to save dirty nodes, because it wll update all the element soon - this.dirtDescendantElementIds_.clear(); + if (this.dirtDescendantElementIds_.size > 0) { + this.removeFromDirtyList(); + this.dirtDescendantElementIds_.clear(); + } Array.from(this.updateFuncByElmtId.keys()).sort(ViewPU.compareNumber).forEach(elmtId => this.UpdateElement(elmtId)); diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_native_base.d.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_native_base.d.ts index 0bb8526fa8a88878432c7a9566a202e27de3de69..05140b0c9665712ff561b8988103888dee8ce754 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_native_base.d.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_native_base.d.ts @@ -21,6 +21,7 @@ declare class NativeViewPartialUpdate { constructor(thisObj: object); markNeedUpdate(): void; + removeFromDirtyList(): void; findChildById(compilerAssignedUniqueChildId: string): View; syncInstanceId(): void; isFirstRender(): boolean; diff --git a/frameworks/core/components_ng/base/view_partial_update_model.h b/frameworks/core/components_ng/base/view_partial_update_model.h index f93688ad9a3c498e9a8a505cc309a3efb90c76fb..192210d942ceb5ad503f899e91d0ede81e30c370 100644 --- a/frameworks/core/components_ng/base/view_partial_update_model.h +++ b/frameworks/core/components_ng/base/view_partial_update_model.h @@ -76,6 +76,7 @@ public: virtual RefPtr CreateNode(NodeInfoPU&& info) = 0; virtual bool MarkNeedUpdate(const WeakPtr& node) = 0; + virtual void RemoveFromDirtyList(const WeakPtr &node) {}; virtual void FlushUpdateTask(const UpdateTask& task) = 0; virtual void FinishUpdate( const WeakPtr& viewNode, int32_t id, std::function&& emplaceTaskFunc) = 0; diff --git a/frameworks/core/components_ng/base/view_partial_update_model_ng.cpp b/frameworks/core/components_ng/base/view_partial_update_model_ng.cpp index fc40ded128729c9902491e65e944dcd83a69054b..725c0a0575835f5973d830f63d68c0cd61644b5b 100644 --- a/frameworks/core/components_ng/base/view_partial_update_model_ng.cpp +++ b/frameworks/core/components_ng/base/view_partial_update_model_ng.cpp @@ -103,6 +103,16 @@ bool ViewPartialUpdateModelNG::MarkNeedUpdate(const WeakPtr& node) return true; } +void ViewPartialUpdateModelNG::RemoveFromDirtyList(const WeakPtr& node) +{ + auto weakNode = AceType::DynamicCast(node); + auto customNode = weakNode.Upgrade(); + if (!customNode) { + LOGW("cannot remove from dirty list, customNode is invalid"); + } + customNode->RemoveFromDirtyList(); +} + void ViewPartialUpdateModelNG::FinishUpdate( const WeakPtr& viewNode, int32_t id, std::function&& emplaceTaskFunc) { diff --git a/frameworks/core/components_ng/base/view_partial_update_model_ng.h b/frameworks/core/components_ng/base/view_partial_update_model_ng.h index 28c38e0998ded369c60522bad8d11a86c04631cf..3f3566687cd5c2ccea5cc6bb76795c1c6bce3375 100644 --- a/frameworks/core/components_ng/base/view_partial_update_model_ng.h +++ b/frameworks/core/components_ng/base/view_partial_update_model_ng.h @@ -31,6 +31,8 @@ public: bool MarkNeedUpdate(const WeakPtr& node) override; + void RemoveFromDirtyList(const WeakPtr& node) override; + void FlushUpdateTask(const UpdateTask& task) override {} void FinishUpdate(const WeakPtr& viewNode, int32_t id, diff --git a/frameworks/core/components_ng/pattern/custom/custom_node_base.cpp b/frameworks/core/components_ng/pattern/custom/custom_node_base.cpp index 9b7418c80525f445690be6ac7ede992b7b8e0b11..c719c4b98c3213dadb70287d5808427573d9a81f 100644 --- a/frameworks/core/components_ng/pattern/custom/custom_node_base.cpp +++ b/frameworks/core/components_ng/pattern/custom/custom_node_base.cpp @@ -282,6 +282,17 @@ void CustomNodeBase::MarkNeedUpdate() context->AddDirtyCustomNode(AceType::DynamicCast(Claim(this))); } +void CustomNodeBase::RemoveFromDirtyList() +{ + auto context = PipelineContext::GetCurrentContext(); + if (!context) { + TAG_LOGW(AceLogTag::ACE_STATE_MGMT, "context no longer exist when [%{public}s] call RemoveFromDirtyList", + GetJSViewName().c_str()); + return; + } + context->RemoveFromDirtyList(AceType::DynamicCast(Claim(this))); +} + void CustomNodeBase::FireRecycleSelf() { auto uiNode = AceType::DynamicCast(Claim(this)); diff --git a/frameworks/core/components_ng/pattern/custom/custom_node_base.h b/frameworks/core/components_ng/pattern/custom/custom_node_base.h index f9d3b0e0a8ae72d3d5c99ebc9384c20f61e93f15..924344c444eb4be511437f7c99cec6e3d3452c12 100644 --- a/frameworks/core/components_ng/pattern/custom/custom_node_base.h +++ b/frameworks/core/components_ng/pattern/custom/custom_node_base.h @@ -74,6 +74,7 @@ public: void Update(); // called by pipeline in js thread of update. void MarkNeedUpdate(); // called by view in js thread + void RemoveFromDirtyList(); // called by view in js thread // called for Component reuse void ResetRecycle(); diff --git a/frameworks/core/pipeline_ng/pipeline_context.cpp b/frameworks/core/pipeline_ng/pipeline_context.cpp index 75da308368b9c22a25ae19421ea12a3d0ea5f6ed..b6dc51f7c650c5c1e11bca9b054f10fc12781420 100755 --- a/frameworks/core/pipeline_ng/pipeline_context.cpp +++ b/frameworks/core/pipeline_ng/pipeline_context.cpp @@ -356,6 +356,29 @@ void PipelineContext::AddDirtyCustomNode(const RefPtr& dirtyNode) RequestFrame(); } +void PipelineContext::RemoveFromDirtyList(const RefPtr& dirtyNode) +{ + CHECK_RUN_ON(UI); + if (!dirtyNode) { + LOGW("dirtyNode invalid"); + return; + } + auto customNode = DynamicCast(dirtyNode); + if (customNode && !dirtyNode->GetInspectorIdValue("").empty()) { + ACE_BUILD_TRACE_BEGIN("RemoveFromDirtyList[%s][self:%d][parent:%d][key:%s]", + customNode->GetJSViewName().c_str(), + dirtyNode->GetId(), dirtyNode->GetParent() ? dirtyNode->GetParent()->GetId() : 0, + dirtyNode->GetInspectorIdValue("").c_str()); + ACE_BUILD_TRACE_END() + } else if (customNode) { + ACE_BUILD_TRACE_BEGIN("RemoveFromDirtyList[%s][self:%d][parent:%d]", + customNode->GetJSViewName().c_str(), + dirtyNode->GetId(), dirtyNode->GetParent() ? dirtyNode->GetParent()->GetId() : 0); + ACE_BUILD_TRACE_END() + } + dirtyNodes_.erase(dirtyNode); +} + void PipelineContext::AddDirtyLayoutNode(const RefPtr& dirty) { CHECK_RUN_ON(UI); diff --git a/frameworks/core/pipeline_ng/pipeline_context.h b/frameworks/core/pipeline_ng/pipeline_context.h index 36d77b6c5ecb74e328de455d0f6745e90a0eb979..3b8ecb813210ad2d4774af4f78e8b14fb5ec413e 100755 --- a/frameworks/core/pipeline_ng/pipeline_context.h +++ b/frameworks/core/pipeline_ng/pipeline_context.h @@ -384,6 +384,8 @@ public: void AddDirtyCustomNode(const RefPtr& dirtyNode); + void RemoveFromDirtyList(const RefPtr& dirtyNode); + void AddDirtyLayoutNode(const RefPtr& dirty); void AddIgnoreLayoutSafeAreaBundle(IgnoreLayoutSafeAreaBundle&& bundle); diff --git a/test/mock/core/pipeline/mock_pipeline_context.cpp b/test/mock/core/pipeline/mock_pipeline_context.cpp index 70a24f16b865fe1a8d0f0d38dec012c9c6379ebd..7eae258d3fa60199ab3c72c852b32dfc0b56841e 100644 --- a/test/mock/core/pipeline/mock_pipeline_context.cpp +++ b/test/mock/core/pipeline/mock_pipeline_context.cpp @@ -826,6 +826,8 @@ bool PipelineContext::GetRestoreInfo(int32_t restoreId, std::string& restoreInfo void PipelineContext::AddDirtyCustomNode(const RefPtr& dirtyNode) {} +void PipelineContext::RemoveFromDirtyList(const RefPtr& dirtyNode) {} + void PipelineContext::SetFlushTSUpdates(std::function&& flushTSUpdates) {} void PipelineContext::AddWindowSizeChangeCallback(int32_t nodeId) {}