mirror of
https://github.com/Tencent/Hippy.git
synced 2026-10-25 18:50:35 +08:00
feat(dom): lazy layout
This commit is contained in:
@@ -83,6 +83,7 @@ class DomManager: public std::enable_shared_from_this<DomManager> {
|
||||
using DomOperation = std::function<void(void)>;
|
||||
std::vector<DomOperation> batched_operations_;
|
||||
std::vector<DomOperation> listener_operations_;
|
||||
std::vector<DomOperation> layout_operations_;
|
||||
std::vector<std::shared_ptr<DomNode>> layout_changed_nodes_;
|
||||
void HandleEvent(const std::shared_ptr<DomEvent>& event);
|
||||
void AddLayoutChangedNode(const std::shared_ptr<DomNode>& node);
|
||||
|
||||
@@ -14,8 +14,11 @@ class LayerOptimizedRenderManager : public RenderManager {
|
||||
void DeleteRenderNode(std::vector<std::shared_ptr<DomNode>>&& nodes) override;
|
||||
void UpdateLayout(const std::vector<std::shared_ptr<DomNode>>& nodes) override;
|
||||
void MoveRenderNode(std::vector<int32_t>&& 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<DomNode> dom_node, const std::string& name) override;
|
||||
void RemoveEventListener(std::weak_ptr<DomNode> dom_node, const std::string& name) override;
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#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<int32_t>&& 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<DomNode> dom_node, const std::string& name) = 0;
|
||||
virtual void RemoveEventListener(std::weak_ptr<DomNode> dom_node, const std::string& name) = 0;
|
||||
virtual void AddRenderListener(std::weak_ptr<DomNode> dom_node, const std::string& name) = 0;
|
||||
virtual void RemoveRenderListener(std::weak_ptr<DomNode> dom_node, const std::string& name) = 0;
|
||||
virtual void CallFunction(std::weak_ptr<DomNode> dom_node, const std::string& name,
|
||||
const DomArgument& param,
|
||||
CallFunctionCallback cb) = 0;
|
||||
virtual void CallFunction(std::weak_ptr<DomNode> dom_node, const std::string& name, const DomArgument& param,
|
||||
CallFunctionCallback cb) = 0;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -42,6 +42,14 @@ void DomManager::CreateDomNodes(std::vector<std::shared_ptr<DomNode>>&& 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<std::shared_ptr<DomNode>>&& 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<std::shared_ptr<DomNode>>&& 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_);
|
||||
}
|
||||
|
||||
@@ -90,14 +90,14 @@ void DomNode::AddChildAt(const std::shared_ptr<DomNode>& 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> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,10 @@ void LayerOptimizedRenderManager::Batch() {
|
||||
render_manager_->Batch();
|
||||
}
|
||||
|
||||
void LayerOptimizedRenderManager::BeforeLayout() {}
|
||||
|
||||
void LayerOptimizedRenderManager::AfterLayout() {}
|
||||
|
||||
void LayerOptimizedRenderManager::AddEventListener(std::weak_ptr<DomNode> dom_node,
|
||||
const std::string &name) {
|
||||
render_manager_->AddEventListener(dom_node, name);
|
||||
|
||||
@@ -27,6 +27,9 @@ class HippyRenderManager : public RenderManager {
|
||||
void MoveRenderNode(std::vector<int32_t>&& 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<DomNode> dom_node, const std::string& name) override;
|
||||
|
||||
@@ -160,6 +160,12 @@ void HippyRenderManager::UpdateLayout(const std::vector<std::shared_ptr<DomNode>
|
||||
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<DomNode> dom_node, const std::string& name) {
|
||||
event_listener_ops_.emplace_back(EventListenerOp(true, dom_node, name));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user