OpenHarmony源码解读系列:ArkUI Engine 导读
本文作者
作者:Pika
链接:
https://juejin.cn/post/7344260655757557797
本文由作者授权发布。
注意鸿蒙系统一直在更新,源码可能会有变更,但是核心体系结构变化不会太大,依旧可以帮助大家建立对鸿蒙源码体系的认知。
本系列是基于OpenHarmony中关键的ArkUI Engine 进行分析,所需要的源码可以通过以下链接下载arkui_ace_engine。UI是作为OpenHarmony系统中最关键的页面展示元素,UI框架的设计往往关系着系统流畅度的具体表现,本系列讲的engine,是指ArkUI的framework层,engine大部分代码由C++实现,其中少部分的ts/js属于部分映射。
https://gitee.com/openharmony/arkui_ace_engine
推荐阅读人员
engine是如何把UI进行分层 engine的三棵树 engine是如何对接平台层 了解ArkUI 控件在C++的实现
环境配置
AOSP implements OpenHarmony
可能大家会有误解,虽然AOSP 远远早于OpenHarmony,但是OpenHarmony其实是以AOSP先作为实现类再定义出接口,这样才能兼容当前所有的Andriod手机,因此后续即使剔除AOSP后,也能够继续以其他实现完成。但是以AOSP先作为实现类再设计出抽象的后果便是,接口定义与系统设计其实是受限于android的定义的。因此关于next版本的设计,相信广大开发者都很好奇。
表示层:面向开发人员的最上层UI抽象,比如Android的View 或者Compose里面的Composable等,都是具体UI的抽象,比如Flutter的Widget。 中间层:中间层,比如android 把View变成一个个RenderNode,用于进一步抽象,用于描述Skia绘制的命令等,其他UI框架比如Flutter也是,不同于Android的实现RenderNode,而是自己抽象一个个RenderObject,通过RenderObject生成Scene给到实现层(Flutter Engine)进行绘制。 实现层:依托于具体图形标准实现,比如OpenGL/VulKan,这一层是真正的图形绘制,比如我们可以在Andorid直接通过OpenGL绘制出形状。因为直接通过OpenGL绘制会比较复杂,因此往往还会抽象出一层,比如Skia。
表示层
abstract class ViewPU extends NativeViewPartialUpdate
implements IViewPropertiesChangeSubscriber {
abstract class View extends NativeViewFullUpdate implements
IMultiPropertiesChangeSubscriber, IMultiPropertiesReadSubscriber {
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
.....
declare class NativeViewPartialUpdate {
constructor( );
markNeedUpdate(): void;
findChildById(compilerAssignedUniqueChildId: string): View;
syncInstanceId(): void;
isFirstRender(): boolean;
restoreInstanceId(): void;
static create(newView: NativeViewPartialUpdate): void;
finishUpdateFunc(elmtId: number): void;
isLazyItemRender(elmtId : number) : boolean;
setCardId(cardId: number): void;
getCardId(): number;
resetRecycleCustomNode(): void;
}
interface IViewPropertiesChangeSubscriber extends IPropertySubscriber {
// ViewPU get informed when View variable has changed
// informs the elmtIds that need update upon variable change
viewPropertyHasChanged(varName: PropertyInfo, dependentElmtIds: Set<number>): void ;
}
中间层
namespace OHOS::Ace::Flutter {
void Layer::AddChildren(const RefPtr<Layer>& layer)
{
auto it = std::find(children_.begin(), children_.end(), layer);
if (it == children_.end()) {
layer->SetParent(AceType::Claim(this));
children_.push_back(layer);
}
}
void Layer::DumpTree(int32_t depth)
{
if (DumpLog::GetInstance().GetDumpFile()) {
Dump();
DumpLog::GetInstance().Print(depth, AceType::TypeName(this), children_.size());
}
for (const auto& item : children_) {
item->DumpTree(depth + 1);
}
}
} // namespace OHOS::Ace::Flutter
class ACE_EXPORT Component : public virtual AceType {
DECLARE_ACE_TYPE(Component, AceType);
public:
Component();
~Component() override;
virtual RefPtr<Element> CreateElement() = 0;
class RenderComponent : public Component {
DECLARE_ACE_TYPE(RenderComponent, Component);
RenderComponent特有方法
virtual RefPtr<RenderNode> CreateRenderNode() = 0;
// A component can compose others components.
class ACE_EXPORT BaseComposedComponent : public Component {
DECLARE_ACE_TYPE(BaseComposedComponent, Component);
class ACE_EXPORT Element : public virtual AceType {
DECLARE_ACE_TYPE(Element, AceType);
public:
Element() = default;
~Element();
void AddChild(const RefPtr<Element>& child, int32_t slot = DEFAULT_ELEMENT_SLOT);
void RemoveChild(const RefPtr<Element>& child);
RefPtr<Element> GetChildBySlot(int32_t slot);
void DeactivateChild(RefPtr<Element> child);
void Rebuild();
// RenderNode is the base class for different render backend, represent a render unit for render pipeline.
class ACE_EXPORT RenderNode : public PropertyAnimatable, public AnimatableProperties, public virtual AceType {
DECLARE_ACE_TYPE(RenderNode, PropertyAnimatable, AceType);
public:
using OpacityCallback = std::function<void(uint8_t)>;
using SlipFactorSetting = std::function<void(double)>;
~RenderNode() override = default;
static void MarkTreeRender(const RefPtr<RenderNode>& root, bool& meetHole, bool needFlush);
static void MarkWholeRender(const WeakPtr<RenderNode>& nodeWeak, bool needFlush);
void SetZIndex(int32_t zIndex)
{
zIndex_ = zIndex;
}
int32_t GetZIndex() const
{
return zIndex_;
}
实现层
void FlutterRenderContext::StartRecording()
{
currentLayer_ = AceType::MakeRefPtr<PictureLayer>();
recorder_ = flutter::PictureRecorder::Create();
canvas_ = flutter::Canvas::Create(
recorder_.get(), estimatedRect_.Left(), estimatedRect_.Top(), estimatedRect_.Right(), estimatedRect_.Bottom());
if (clipHole_.IsValid()) {
canvas_->save();
needRestoreHole_ = true;
canvas_->clipRect(
clipHole_.Left(), clipHole_.Top(), clipHole_.Right(), clipHole_.Bottom(), SkClipOp::kDifference);
}
containerLayer_->AddChildren(currentLayer_);
}
本篇作为ArkUI Engine系列的导读,希望能够让读者对整体框架有一个大概的了解,通过建立较为全面的思维导图之后,接下来的学习就能够更加轻松。本系列将着重于中间层的实现,读者们需要对表示层的基础UI,比如ForEach,普通的View比如Row有个大致了解即可。
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!