From d9dc87f45cfcef61582f5e758820df2e90dc2368 Mon Sep 17 00:00:00 2001 From: charleeshen Date: Wed, 29 Dec 2021 10:20:14 +0800 Subject: [PATCH] feat(dom): lazy layout --- dom/include/dom/dom_manager.h | 1 + .../dom/layer_optimized_render_manager.h | 5 +- dom/include/dom/render_manager.h | 12 ++-- dom/src/dom/dom_manager.cc | 55 ++++++++++++++++--- dom/src/dom/dom_node.cc | 4 +- dom/src/dom/layer_optimized_render_manager.cc | 4 ++ .../jni/include/render/hippy_render_manager.h | 3 + .../jni/src/render/hippy_render_manager.cc | 9 +++ 8 files changed, 78 insertions(+), 15 deletions(-) diff --git a/dom/include/dom/dom_manager.h b/dom/include/dom/dom_manager.h index fe5193967..402739ccf 100644 --- a/dom/include/dom/dom_manager.h +++ b/dom/include/dom/dom_manager.h @@ -83,6 +83,7 @@ class DomManager: public std::enable_shared_from_this { using DomOperation = std::function; std::vector batched_operations_; std::vector listener_operations_; + std::vector layout_operations_; std::vector> layout_changed_nodes_; void HandleEvent(const std::shared_ptr& event); void AddLayoutChangedNode(const std::shared_ptr& node); diff --git a/dom/include/dom/layer_optimized_render_manager.h b/dom/include/dom/layer_optimized_render_manager.h index 9ffb76182..5d44f2857 100644 --- a/dom/include/dom/layer_optimized_render_manager.h +++ b/dom/include/dom/layer_optimized_render_manager.h @@ -14,8 +14,11 @@ class LayerOptimizedRenderManager : public RenderManager { void DeleteRenderNode(std::vector>&& nodes) override; void UpdateLayout(const std::vector>& nodes) override; void MoveRenderNode(std::vector&& moved_ids, int32_t from_pid, int32_t to_pid) override; - void Batch() override; + + void BeforeLayout() override; + void AfterLayout() override; + void AddEventListener(std::weak_ptr dom_node, const std::string& name) override; void RemoveEventListener(std::weak_ptr dom_node, const std::string& name) override; diff --git a/dom/include/dom/render_manager.h b/dom/include/dom/render_manager.h index 47352e49f..cc4301ef8 100644 --- a/dom/include/dom/render_manager.h +++ b/dom/include/dom/render_manager.h @@ -4,10 +4,10 @@ #include #include -#include "dom/dom_listener.h" -#include "dom/dom_value.h" #include "dom/dom_argument.h" +#include "dom/dom_listener.h" #include "dom/dom_node.h" +#include "dom/dom_value.h" namespace hippy { inline namespace dom { @@ -25,14 +25,16 @@ class RenderManager { virtual void MoveRenderNode(std::vector&& moved_ids, int32_t from_pid, int32_t to_pid) = 0; virtual void Batch() = 0; + virtual void BeforeLayout() = 0; + virtual void AfterLayout() = 0; + using DomArgument = hippy::dom::DomArgument; virtual void AddEventListener(std::weak_ptr dom_node, const std::string& name) = 0; virtual void RemoveEventListener(std::weak_ptr dom_node, const std::string& name) = 0; virtual void AddRenderListener(std::weak_ptr dom_node, const std::string& name) = 0; virtual void RemoveRenderListener(std::weak_ptr dom_node, const std::string& name) = 0; - virtual void CallFunction(std::weak_ptr dom_node, const std::string& name, - const DomArgument& param, - CallFunctionCallback cb) = 0; + virtual void CallFunction(std::weak_ptr dom_node, const std::string& name, const DomArgument& param, + CallFunctionCallback cb) = 0; }; } // namespace dom diff --git a/dom/src/dom/dom_manager.cc b/dom/src/dom/dom_manager.cc index 73b56ef02..fe1f37b1c 100644 --- a/dom/src/dom/dom_manager.cc +++ b/dom/src/dom/dom_manager.cc @@ -42,6 +42,14 @@ void DomManager::CreateDomNodes(std::vector>&& nodes) { node->ParseLayoutStyleInfo(); parent_node->AddChildAt(node, node->GetIndex()); + // 延迟构造layout tree + auto layout_node = node->GetLayoutNode(); + auto parent_layout_node = parent_node->GetLayoutNode(); + uint32_t index = node->GetIndex(); + self->layout_operations_.emplace_back([layout_node, parent_layout_node, index]() { + parent_layout_node->InsertChild(layout_node, index); + }); + self->dom_node_registry_.AddNode(node); self->HandleListener(node, kOnDomCreated, nullptr); } @@ -74,9 +82,16 @@ void DomManager::UpdateDomNodes(std::vector>&& nodes) { node->SetStyleMap(it->get()->GetStyleMap()); node->SetExtStyleMap(it->get()->GetExtStyle()); node->SetDiffStyle(std::move(style_diff)); - node->ParseLayoutStyleInfo(); + // node->ParseLayoutStyleInfo(); update_nodes.push_back(node); self->HandleListener(node, kOnDomUpdated, nullptr); + + // 延迟更新 layout tree + int32_t id = node->GetId(); + self->layout_operations_.emplace_back([self, id]() { + auto node = self->dom_node_registry_.GetNode(id); + node->ParseLayoutStyleInfo(); + }); } if (!update_nodes.empty()) { @@ -107,6 +122,13 @@ void DomManager::DeleteDomNodes(std::vector>&& nodes) { self->dom_node_registry_.RemoveNode(node->GetId()); delete_nodes.push_back(node); self->HandleListener(node, kOnDomDeleted, nullptr); + + // 延迟删除 layout tree + auto layout_node = node->GetLayoutNode(); + auto parent_layout_node = parent_node->GetLayoutNode(); + self->layout_operations_.emplace_back([layout_node, parent_layout_node]() { + parent_layout_node->RemoveChild(layout_node); + }); } if (!delete_nodes.empty()) { @@ -135,15 +157,24 @@ void DomManager::EndBatch() { listener_operation(); } self->listener_operations_.clear(); - // 触发布局计算 - self->layout_changed_nodes_.clear(); - // 触发布局计算 - self->root_node_->DoLayout(); auto render_manager = self->render_manager_.lock(); TDF_BASE_DCHECK(render_manager); if (!render_manager) { return; } + // Before Layout + render_manager->BeforeLayout(); + // build layout tree + for (auto& layout_operation : self->layout_operations_) { + layout_operation(); + } + self->layout_operations_.clear(); + // 清理布局计算 + self->layout_changed_nodes_.clear(); + // 触发布局计算 + self->root_node_->DoLayout(); + // After Layout + render_manager->AfterLayout(); if (!self->layout_changed_nodes_.empty()) { render_manager->UpdateLayout(self->layout_changed_nodes_); } @@ -254,13 +285,23 @@ void DomManager::DoLayout() { PostTask([WEAK_THIS]() { DEFINE_AND_CHECK_SELF(DomManager) self->layout_changed_nodes_.clear(); - // 触发布局计算 - self->root_node_->DoLayout(); auto render_manager = self->render_manager_.lock(); TDF_BASE_DCHECK(render_manager); if (!render_manager) { return; } + // Before Layout + render_manager->BeforeLayout(); + // build layout tree + for (auto& layout_operation : self->layout_operations_) { + layout_operation(); + } + self->layout_operations_.clear(); + + // 触发布局计算 + self->root_node_->DoLayout(); + // After Layout + render_manager->AfterLayout(); if (!self->layout_changed_nodes_.empty()) { render_manager->UpdateLayout(self->layout_changed_nodes_); } diff --git a/dom/src/dom/dom_node.cc b/dom/src/dom/dom_node.cc index cb27432f5..3cf7640c9 100644 --- a/dom/src/dom/dom_node.cc +++ b/dom/src/dom/dom_node.cc @@ -90,14 +90,14 @@ void DomNode::AddChildAt(const std::shared_ptr& dom_node, int32_t index children_.insert(it, dom_node); } dom_node->SetParent(shared_from_this()); - layout_node_->InsertChild(dom_node->layout_node_, insert_index); + // layout_node_->InsertChild(dom_node->layout_node_, insert_index); } std::shared_ptr DomNode::RemoveChildAt(int32_t index) { auto child = children_[index]; child->SetParent(nullptr); children_.erase(children_.begin() + index); - layout_node_->RemoveChild(child->layout_node_); + // layout_node_->RemoveChild(child->layout_node_); return child; } diff --git a/dom/src/dom/layer_optimized_render_manager.cc b/dom/src/dom/layer_optimized_render_manager.cc index e77fabf1e..dc1ea9e1d 100644 --- a/dom/src/dom/layer_optimized_render_manager.cc +++ b/dom/src/dom/layer_optimized_render_manager.cc @@ -89,6 +89,10 @@ void LayerOptimizedRenderManager::Batch() { render_manager_->Batch(); } +void LayerOptimizedRenderManager::BeforeLayout() {} + +void LayerOptimizedRenderManager::AfterLayout() {} + void LayerOptimizedRenderManager::AddEventListener(std::weak_ptr dom_node, const std::string &name) { render_manager_->AddEventListener(dom_node, name); diff --git a/renderer/native/android/src/main/jni/include/render/hippy_render_manager.h b/renderer/native/android/src/main/jni/include/render/hippy_render_manager.h index 2e8e8cf18..c9890e80a 100644 --- a/renderer/native/android/src/main/jni/include/render/hippy_render_manager.h +++ b/renderer/native/android/src/main/jni/include/render/hippy_render_manager.h @@ -27,6 +27,9 @@ class HippyRenderManager : public RenderManager { void MoveRenderNode(std::vector&& moved_ids, int32_t from_pid, int32_t to_pid) override; void Batch() override; + void BeforeLayout() override; + void AfterLayout() override; + using DomValue = tdf::base::DomValue; void AddEventListener(std::weak_ptr dom_node, const std::string& name) override; diff --git a/renderer/native/android/src/main/jni/src/render/hippy_render_manager.cc b/renderer/native/android/src/main/jni/src/render/hippy_render_manager.cc index ed98859c2..67961113c 100644 --- a/renderer/native/android/src/main/jni/src/render/hippy_render_manager.cc +++ b/renderer/native/android/src/main/jni/src/render/hippy_render_manager.cc @@ -160,6 +160,12 @@ void HippyRenderManager::UpdateLayout(const std::vector dom_node[kHeight] = tdf::base::DomValue(DpToPx(result.height)); dom_node[kLeft] = tdf::base::DomValue(DpToPx(result.left)); dom_node[kTop] = tdf::base::DomValue(DpToPx(result.top)); + if(nodes[i]->GetViewName() == kView) { + dom_node["paddingLeft"] = tdf::base::DomValue(DpToPx(result.padding[0])); + dom_node["paddingTop"] = tdf::base::DomValue(DpToPx(result.padding[1])); + dom_node["paddingRight"] = tdf::base::DomValue(DpToPx(result.padding[2])); + dom_node["paddingBottom"] = tdf::base::DomValue(DpToPx(result.padding[3])); + } dom_node_array[i] = dom_node; } serializer_->WriteDenseJSArray(dom_node_array); @@ -201,6 +207,9 @@ void HippyRenderManager::Batch() { return; }; +void BeforeLayout() {}; +void AfterLayout() {}; + void HippyRenderManager::AddEventListener(std::weak_ptr dom_node, const std::string& name) { event_listener_ops_.emplace_back(EventListenerOp(true, dom_node, name)); }