Skip to content

Commit

Permalink
Merge branch 'main' into layout_event
Browse files Browse the repository at this point in the history
  • Loading branch information
open-hippy authored Nov 3, 2023
2 parents bef6515 + 79ed489 commit 5513fd4
Show file tree
Hide file tree
Showing 335 changed files with 7,057 additions and 6,098 deletions.
16 changes: 8 additions & 8 deletions docs/architecture/render/ios/native-render.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

Hippy抽象了RenderManager的接口,允许接入方自行实现RenderManager接口,并实现上屏操作。其中Native Renderer由Hippy默认实现,通过Native组件构建出整个Hippy界面。

NativeRenderManager负责实现Hippy::RenderManager的抽象接口,并将Render树的构建与UI上屏的行为交由NativeRenderImpl处理
NativeRenderManager负责实现Hippy::RenderManager的抽象接口,并将Render树的构建与UI上屏的行为交由HippyUIManager处理

NativeRenderImpl负责处理以下行为
HippyUIManager负责处理以下行为

- Render节点的创建与管理
- RooView与RootNode绑定与管理(不持有)
Expand Down Expand Up @@ -58,7 +58,7 @@ NativeRenderImpl负责处理以下行为:

为此,需要设定render节点的懒加载属性,以保证UI的懒创建。

在iOS中,此能力由`[NativeRenderObjectView creationType:NativeRenderCreationType]`属性控制。
在iOS中,此能力由`[HippyShadowView creationType:NativeRenderCreationType]`属性控制。
![image](../../../assets/img/lazy_load1.png)
对于懒加载组件,需要手动调用创建方法才会创建。
![image](../../../assets/img/lazy_load2.png)
Expand Down Expand Up @@ -141,13 +141,13 @@ Text组件算是一个比较特殊的组件,相对于其他组件,其有两

各业务会选择不同的图片格式就计入,而iOS api默认支持的图片格式有限。这种情况下,需要提供接口,处理默认不支持的图片格式解码。

为此我们声明了一份协议HPImageProviderProtocol,专门处理各类型Image的解码工作。
为此我们声明了一份协议HippyImageProviderProtocol,专门处理各类型Image的解码工作。

接入方如果有自定义格式,需要实现一份protocol。

#### HPImageProviderProtocol
#### HippyImageProviderProtocol

`HPImageProviderProtocol`包含有两类方法:必须实现的和可选实现的。
`HippyImageProviderProtocol`包含有两类方法:必须实现的和可选实现的。

必须实现的方法负责处理图片解码的基本操作,而可选实现的用于处理动图。
接入方可同时添加多个解码器,HippySDK 在需要时,会按照解码器添加反序询问各解码器能否处理当前数据。如果不能,则会询问下个解码器,直至获取了对应的解码器,或者使用默认解码器。
Expand All @@ -167,7 +167,7 @@ Text组件算是一个比较特殊的组件,相对于其他组件,其有两
| -(NSUIneger)loopCount | 返回动图循环次数 |
| -(double)delayTimeAtFrame:(NSUInteger)frame | 返回指定帧延迟时长 |

#### HPDefaultImageProvider
#### HippyDefaultImageProvider

Hippy3.0默认实现了一套decoder作为默认decoder,实现对系统支持的格式进行解码操作。任何没有decoder处理的数据,最终都会由HippyDefaultImageProvider调用系统API CGImageSource进行处理。

Expand All @@ -178,6 +178,6 @@ Hippy3.0默认实现了一套decoder作为默认decoder,实现对系统支持
- Hipp3.0SDK的动图逻辑由NativeRenderAnimatedImage和NativeRenderAnimatedImageView负责。
- 这是一个生产者-消费者模型。NativeRenderAnimatedImage负责生产,NativeRenderAnimatedImageView负责消费。
- NativeRenderAnimatedImageView实现一个vsync回调,每次回调向NativeRenderAnimatedImage询问当前帧对应的Image
- NativeRenderAnimatedImage持有HPImageProviderProtocol实例,负责解析动图,并返回对应帧的Image
- NativeRenderAnimatedImage持有HippyImageProviderProtocol实例,负责解析动图,并返回对应帧的Image

![image](../../../assets/img/animated_image.png)
48 changes: 24 additions & 24 deletions docs/development/native-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,13 @@ protected void onAttachedToWindow() {
## 创建对应的ViewManager

> ViewManager 是对应的视图管理组件,负责前端视图和终端视图直接进行属性、方法的调用。
> SDK 中最基础的 `ViewManager``NativeRenderViewManager`,封装了基本的方法,负责管理 `NativeRenderView`
> 用户自定的 `ViewManager` 必须继承自 `NativeRenderViewManager`
> SDK 中最基础的 `ViewManager``HippyViewManager`,封装了基本的方法,负责管理 `NativeRenderView`
> 用户自定的 `ViewManager` 必须继承自 `HippyViewManager`
NativeRenderMyViewManager.h

```objectivec
@interface NativeRenderMyViewManager:NativeRenderViewManager
@interface NativeRenderMyViewManager:HippyViewManager
@end
```

Expand All @@ -198,15 +198,15 @@ NativeRenderMyViewManager.m
```objectivec
@implementation NativeRenderMyViewManager

NATIVE_RENDER_EXPORT_VIEW(MyView)
HIPPY_EXPORT_MODULE(MyView)

NATIVE_RENDER_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor)
NATIVE_RENDER_REMAP_VIEW_PROPERTY(opacity, alpha, CGFloat)
HIPPY_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor)
HIPPY_REMAP_VIEW_PROPERTY(opacity, alpha, CGFloat)

NATIVE_RENDER_CUSTOM_VIEW_PROPERTY(overflow, CSSOverflow, NativeRenderView)
HIPPY_CUSTOM_VIEW_PROPERTY(overflow, CSSOverflow, HippyView)
{
if (json) {
view.clipsToBounds = [HPConvert CSSOverflow:json] != CSSOverflowVisible;
view.clipsToBounds = [HippyConvert CSSOverflow:json] != CSSOverflowVisible;
} else {
view.clipsToBounds = defaultView.clipsToBounds;
}
Expand All @@ -216,15 +216,15 @@ NATIVE_RENDER_CUSTOM_VIEW_PROPERTY(overflow, CSSOverflow, NativeRenderView)
return [[NativeRenderMyView alloc] init];
}

- (NativeRenderObjectView *)shadowView {
return [[NativeRenderObjectView alloc] init];
- (HippyShadowView *)shadowView {
return [[HippyShadowView alloc] init];
}

NATIVE_RENDER_COMPONENT_EXPORT_METHOD(focus:(nonnull NSNumber *)reactTag) {
HIPPY_EXPORT_METHOD(focus:(nonnull NSNumber *)reactTag) {
// do sth
}

NATIVE_RENDER_COMPONENT_EXPORT_METHOD(focus:(nonnull NSNumber *)reactTag callback:(RenderUIResponseSenderBlock)callback) {
HIPPY_EXPORT_METHOD(focus:(nonnull NSNumber *)reactTag callback:(HippyPromiseResolveBlock)callback) {
// do sth
NSArray *result = xxx;
callback(result);
Expand All @@ -233,42 +233,42 @@ NATIVE_RENDER_COMPONENT_EXPORT_METHOD(focus:(nonnull NSNumber *)reactTag callbac
## 类型导出
`NATIVE_RENDER_EXPORT_VIEW()` 将`NativeRenderMyViewManager` 类注册,前端在对 `MyView` 进行操作时会通过 `NativeRenderMyViewManager` 进行实例对象指派。
`HIPPY_EXPORT_MODULE()` 将`NativeRenderMyViewManager` 类注册,前端在对 `MyView` 进行操作时会通过 `NativeRenderMyViewManager` 进行实例对象指派。
`NATIVE_RENDER_EXPORT_VIEW()`中的参数可选。代表的是 `ViewManager` 对应的View名称。
`HIPPY_EXPORT_MODULE()`中的参数可选。代表的是 `ViewManager` 对应的View名称。
若用户不填写,则默认使用类名称。
## 参数导出
`NATIVE_RENDER_EXPORT_VIEW_PROPERTY` 将终端View的参数和前端参数绑定。当前端设定参数值时,会自动调用 setter 方法设置到终端对应的参数。
`HIPPY_EXPORT_VIEW_PROPERTY` 将终端View的参数和前端参数绑定。当前端设定参数值时,会自动调用 setter 方法设置到终端对应的参数。
`NATIVE_RENDER_REMAP_VIEW_PROPERTY()` 负责将前端对应的参数名和终端对应的参数名对应起来。以上述代码为例,前端的`opacity` 参数对应终端的`alpha`参数。此宏一共包含三个参数,第一个为前端参数名,第二个为对应的终端参数名称,第三个为参数类型。另外,此宏在设置终端参数时使用的是`keyPath`方法,即终端可以使用`keyPath`参数。
`HIPPY_REMAP_VIEW_PROPERTY()` 负责将前端对应的参数名和终端对应的参数名对应起来。以上述代码为例,前端的`opacity` 参数对应终端的`alpha`参数。此宏一共包含三个参数,第一个为前端参数名,第二个为对应的终端参数名称,第三个为参数类型。另外,此宏在设置终端参数时使用的是`keyPath`方法,即终端可以使用`keyPath`参数。
`NATIVE_RENDER_CUSTOM_VIEW_PROPERTY()` 允许终端自行解析前端参数。SDK将前端传递过来的原始json类型数据传递给函数体(用户可以使用`HPConvert`类中的方法解析对应的数据),用户获取后自行解析。
`HIPPY_CUSTOM_VIEW_PROPERTY()` 允许终端自行解析前端参数。SDK将前端传递过来的原始json类型数据传递给函数体(用户可以使用`HippyConvert`类中的方法解析对应的数据),用户获取后自行解析。
>这个方法带有两个隐藏参数-`view`, `defaultView`。`view`是指当前前端要求渲染的view。`defaultView`指当前端渲染参数为nil时创建的一个临时view,使用其默认参数赋值。
## 方法导出
`NATIVE_RENDER_COMPONENT_EXPORT_METHOD` 能够使前端随时调用终端对应的方法。前端通过三种模式调用,分别是 `callNative`, `callNativeWithCallbackId`。终端调用这三种方式时,函数体写法可以参照上面的示例。
`HIPPY_EXPORT_METHOD` 能够使前端随时调用终端对应的方法。前端通过三种模式调用,分别是 `callNative`, `callNativeWithCallbackId`。终端调用这三种方式时,函数体写法可以参照上面的示例。
- callNative:此方法不需要终端返回任何值。
- callNativeWithCallbackId: 此方法需要终端在函数体中以单个block形式返回数据。block类型为 `RenderUIResponseSenderBlock`,参数为一个`id`变量。
- callNativeWithCallbackId: 此方法需要终端在函数体中以单个block形式返回数据。block类型为 `HippyPromiseResolveBlock`,参数为一个`id`变量。
一个`ViewManager`可以管理一种类型的多个实例,为了在ViewManager中区分当前操作的是哪个View,每一个导出方法对应的第一个参数都是View对应的tag值,用户可根据这个tag值找到对应操作的view。
> 由于导出方法并不会在主线程中调用,因此如果用户需要进行UI操作,则必须将其分配至主线程。推荐在导出方法中使用[NativeRenderImpl addUIBlock:]方法。其中的block类型为`NativeRenderRenderUIBlock`。
> 由于导出方法并不会在主线程中调用,因此如果用户需要进行UI操作,则必须将其分配至主线程。推荐在导出方法中使用[HippyUIManager addUIBlock:]方法。其中的block类型为`HippyViewManagerUIBlock`。
> `typedef void (^NativeRenderRenderUIBlock)(NativeRenderImpl *renderContext, NSDictionary<NSNumber *, __kindof UIView *> *viewRegistry)`。第二个参数为字典,其中的key就是对应的view tag值,value就是对应的view。
> `typedef void (^HippyViewManagerUIBlock)(HippyUIManager *uiManager, NSDictionary<NSNumber *, __kindof UIView *> *viewRegistry)`。第二个参数为字典,其中的key就是对应的view tag值,value就是对应的view。
## 创建RenderObject和View
在OC层,`NativeRenderImpl`负责构建Render树,对应的每一个节点都是一个RenderObjectView。Render树结构不保证与dom树一致,因为Render可能有自己的渲染逻辑。
在OC层,`HippyUIManager`负责构建Render树,对应的每一个节点都是一个RenderObjectView。Render树结构不保证与dom树一致,因为Render可能有自己的渲染逻辑。
>`NativeRenderView`会根据`NativeRenderObjectView`的映射结果构建真正的View视图。因此对于大多数情况下的自定义view manager来说,直接创建一个`NativeRenderObjectView`即可。
>`NativeRenderView`会根据`HippyShadowView`的映射结果构建真正的View视图。因此对于大多数情况下的自定义view manager来说,直接创建一个`HippyShadowView`即可。
`NativeRenderImpl`将调用[NativeRenderMyViewManager view]方法去创建一个真正的view,用户需要实现这个方法并返回自己所需要的`NativeRenderMyView`。
`HippyUIManager`将调用[NativeRenderMyViewManager view]方法去创建一个真正的view,用户需要实现这个方法并返回自己所需要的`NativeRenderMyView`。
到此,一个简单的`NativeRenderMyViewManager`与`NativeRenderMyView`创建完成。
Expand Down
6 changes: 3 additions & 3 deletions docs/development/native-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ HippyBridge中有些必须属性,需要调用方设置。如果不设置,将
@property(nonatomic, assign)std::weak_ptr<VFSUriLoader> VFSUriLoader;
//添加Image
- (void)addImageProviderClass:(Class<HPImageProviderProtocol>)cls;
- (void)addImageProviderClass:(Class<HippyImageProviderProtocol>)cls;
//调用方代码
_bridge.moduleName = @"Demo"
Expand All @@ -253,7 +253,7 @@ demoLoader->RegisterConvenientUriHandler(@"hpfile", fileHandler);
_bridge.VFSUriLoader = demoLoader; //使用Hippy默认的vfs
//使用系统默认的image解码器
[_bridge addImageProviderClass:[HPDefaultImageProvider class]];
[_bridge addImageProviderClass:[HippyDefaultImageProvider class]];
```

Expand All @@ -279,7 +279,7 @@ auto nativeRenderManager = std::make_shared<NativeRenderManager>();
nativeRenderManager->SetDomManager(domManager);
//设置Image解码类
nativeRenderManager->AddImageProviderClass([HPDefaultImageProvider class]);
nativeRenderManager->AddImageProviderClass([HippyDefaultImageProvider class]);
//设置额外的自定义组件
nativeRenderManager->RegisterExtraComponent(_extraComponents);
//设置vfs系统
Expand Down
2 changes: 1 addition & 1 deletion dom/include/dom/diff_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class DiffUtils {
* k: 11,
* }
*/
static DiffValue DiffProps(const DomValueMap& old_props_map, const DomValueMap& new_props_map);
static DiffValue DiffProps(const DomValueMap& old_props_map, const DomValueMap& new_props_map, bool skip_style_diff);
};
} // namespace dom
} // namespace hippy
11 changes: 10 additions & 1 deletion dom/include/dom/dom_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ enum RelativeType {
kBack = 1,
};

struct DiffInfo {
bool skip_style_diff;
DiffInfo(bool skip_style_diff) : skip_style_diff(skip_style_diff) {}

private:
friend std::ostream& operator<<(std::ostream& os, const DiffInfo& diff_info);
};

struct RefInfo {
uint32_t ref_id;
int32_t relative_to_ref = RelativeType::kDefault;
Expand All @@ -67,7 +75,8 @@ struct RefInfo {
struct DomInfo {
std::shared_ptr<DomNode> dom_node;
std::shared_ptr<RefInfo> ref_info;
DomInfo(std::shared_ptr<DomNode> node, std::shared_ptr<RefInfo> ref) : dom_node(node), ref_info(ref) {}
std::shared_ptr<DiffInfo> diff_info;
DomInfo(std::shared_ptr<DomNode> node, std::shared_ptr<RefInfo> ref, std::shared_ptr<DiffInfo> diff) : dom_node(node), ref_info(ref), diff_info(diff) {}

private:
friend std::ostream& operator<<(std::ostream& os, const DomInfo& dom_info);
Expand Down
6 changes: 5 additions & 1 deletion dom/src/dom/diff_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,13 @@ static bool ShouldUpdateProperty(const std::string& key, const DomValueMap& old_
return false;
}

DiffValue DiffUtils::DiffProps(const DomValueMap& old_props_map, const DomValueMap& new_props_map) {
DiffValue DiffUtils::DiffProps(const DomValueMap& old_props_map, const DomValueMap& new_props_map, bool skip_style_diff) {
std::shared_ptr<DomValueMap> update_props = std::make_shared<DomValueMap>();
std::shared_ptr<std::vector<std::string>> delete_props = std::make_shared<std::vector<std::string>>();
if (skip_style_diff) {
// 跳过 style diff 计算
return std::make_tuple(update_props, delete_props);
}

// delete props
// Example:
Expand Down
2 changes: 1 addition & 1 deletion dom/src/dom/dom_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ bool DomManager::SetSnapShot(const std::shared_ptr<RootNode>& root_node, const b
if (dom_node->GetPid() == orig_root_id) {
dom_node->SetPid(root_node->GetId());
}
nodes.push_back(std::make_shared<DomInfo>(dom_node, nullptr));
nodes.push_back(std::make_shared<DomInfo>(dom_node, nullptr, nullptr));
}

CreateDomNodes(root_node, std::move(nodes));
Expand Down
3 changes: 2 additions & 1 deletion dom/src/dom/dom_manager_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ std::vector<std::shared_ptr<hippy::DomInfo>> ParserJson(const std::string& json_
ref = std::make_shared<hippy::dom::RefInfo>(id, ref_id);
}

std::shared_ptr<hippy::dom::DomInfo> dom_info = std::make_shared<hippy::dom::DomInfo>(dom_node, ref);
auto diff_info = std::make_shared<hippy::dom::DiffInfo>(false);
std::shared_ptr<hippy::dom::DomInfo> dom_info = std::make_shared<hippy::dom::DomInfo>(dom_node, ref, diff_info);
nodes.push_back(dom_info);
}
return nodes;
Expand Down
15 changes: 13 additions & 2 deletions dom/src/dom/dom_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,8 @@ void DomNode::UpdateDiff(const std::unordered_map<std::string,
std::shared_ptr<HippyValue>>& update_style,
const std::unordered_map<std::string,
std::shared_ptr<HippyValue>>& update_dom_ext) {
auto style_diff_value = DiffUtils::DiffProps(*this->GetStyleMap(), update_style);
auto ext_diff_value = DiffUtils::DiffProps(*this->GetExtStyle(), update_dom_ext);
auto style_diff_value = DiffUtils::DiffProps(*this->GetStyleMap(), update_style, false);
auto ext_diff_value = DiffUtils::DiffProps(*this->GetExtStyle(), update_dom_ext, false);
auto style_update = std::get<0>(style_diff_value);
auto ext_update = std::get<0>(ext_diff_value);
std::shared_ptr<DomValueMap> diff_value = std::make_shared<DomValueMap>();
Expand Down Expand Up @@ -607,6 +607,13 @@ std::ostream& operator<<(std::ostream& os, const RefInfo& ref_info) {
return os;
}

std::ostream& operator<<(std::ostream& os, const DiffInfo& diff_info) {
os << "{";
os << "\"skip_style_diff\": " << diff_info.skip_style_diff << ", ";
os << "}";
return os;
}

std::ostream& operator<<(std::ostream& os, const DomNode& dom_node) {
os << "{";
os << "\"id\": " << dom_node.id_ << ", ";
Expand All @@ -633,10 +640,14 @@ std::ostream& operator<<(std::ostream& os, const DomNode& dom_node) {
std::ostream& operator<<(std::ostream& os, const DomInfo& dom_info) {
auto dom_node = dom_info.dom_node;
auto ref_info = dom_info.ref_info;
auto diff_info = dom_info.diff_info;
os << "{";
if (ref_info != nullptr) {
os << "\"ref info\": " << *ref_info << ", ";
}
if (diff_info != nullptr) {
os << "\"diff info\": " << *diff_info << ", ";
}
if (dom_node != nullptr) {
os << "\"dom node\": " << *dom_node << ", ";
}
Expand Down
Loading

0 comments on commit 5513fd4

Please sign in to comment.