#夏日挑战赛#OpenHarmony3.1-ace-formcomponent源码解析 原创 精华
作者:吴亮亮
简介
formcomponent用于展示桌面图标和卡片。
卡片类似于安卓上的小部件,可以显示于桌面上或者在一些其他系统服务页面。
在展示卡片时,使用card_frontend解析hml标记语言,这是与应用展示不同的一种方式。OpenHarmony支持的应用界面开发有js的类web(hml+css+js)和ets两种声明式,在展示卡片时单独使用了这种更轻量的卡片式(也是类web的,hml+css+json)。
图标和卡片虽然来源和管理者不同,但在使用者这里,并无太大区别。桌面上的app图标相当于1*1的卡片, 实现点击跳转到应用, 没有动态刷新(allowUpate=false)。 以下分析都以卡片来进行说明。
代码位置
/foundation/ace/ace_engine/frameworks/
├──bridge
│ ├──card_frontend
│ │ ├──js_card_parser.h
│ │ ├──js_card_parser.cpp
│ │ ├──card_frontend.h
│ │ ├──card_frontend.cpp
│ │ ├──card_frontend_delegate.h
│ │ └──card_frontend_delegate.cpp
│ └──declarative_frontend/jsview
│ ├──js_form.h
│ └──js_form.cpp
└──core
├──common
│ ├──form_manager.h
│ └──form_manager.cpp
└──components/form
├──resource
│ ├──form_request_data.h
│ ├──form_callback_client.h
│ ├──form_manager_resource.h
│ ├──form_manager_resource.cpp
│ ├──form_manager_delegate.h
│ └──form_manager_delegate.cpp
├──form_component.cpp
├──form_component.h
├──form_element.cpp
├──form_element.h
├──render_form_creator.cpp
├──render_form.cpp
├──render_form.h
├──rosen_render_form.cpp
├──rosen_render_form.h
├──flutter_render_form.cpp
├──flutter_render_form.h
├──form_window.cpp
├──form_window.h
├──sub_container.cpp
└──sub_container.h
bridge/card_frontend虽然和declarative_frontend、js_frontend位于同一级目录,但它实际上是给sub_container用的,目前并不是一种开发应用界面的方式。它的作用是解析卡片UI。
bridge/declarative_frontend/jsview下的js_form是将ets中的组件关联到c++的ace引擎组件实例
core/components/form下是ace引擎组件form_component。
系统架构
图 1 系统架构
卡片提供者是ace_form_ability。卡片内容是hml+css+json,ace_form_ability负责里面数据的更新。
使用者是ace_ability,显示卡片先创建ace中组件form_component, 其中的sub_container通过card_frontend来解析前端hml+css+json展示。
一个类比:formmgr相当于服务器,提供者相当于服务器上的服务,使用者相当于客户端。
form_component能与卡片管理者formmgr通信,将卡片被安装的事件告知formmgr。formmgr通知卡片提供者启动ability。
图 2 类图
关键类介绍
- FormComponentAttribute、JSForm
sdk的ts接口以及关联的c++类。它们是将应用里的控件翻译为c++对象。
前端FormComponent创建时设置的属性包括:
id、name、bundle、ability、module、dimension(1*2, 2*2, 2*4, 4*4)、temporary
interface FormComponentInterface {
(value: {
id: number;
name: string;
bundle: string;
ability: string;
module: string;
dimension?: FormDimension;
temporary?: boolean;
}): FormComponentAttribute;
}
JSForm在Create()中创建FormComponent时,将属性通过RequestFormInfo传给FormComponent实例。
设置的回调包括:
onAcquired、onError、onRouter、onUninstall
-
FormComponent、FormElement、RenderForm[RosenRenderForm、FlutterRenderForm]
ace控件三件套,注意RenderForm是继承于RenderSubContainer。
FormComponent保存卡片属性
FormElement在Prepare()中设置FormManagerDelegate的回调方法,在update()中创建SubContainer。
RenderForm中内容很少,因为真正绘制卡片是在SubContainer里面。 -
FormManagerDelegate
能够与pipeline和FormMgr通信。在标准系统中,通过FormMgr管理卡片;[在lite系统中,没有FormMgr,通过pipeline中的PlatformResRegister管理]。
FormMgr主动发起的ipc通过FormCallbackClient调用过来。 -
FormManager
本地管理SubContainer的单实例。 -
SubContainer
真正渲染卡片的地方。
outSidePipelineContext_是整个FormComponent的pipeline,pipelineContext_则是SubContainer自己渲染卡片时用的pipeline。这两句代码可以表明二者的关系:
auto&& window = std::make_unique<FormWindow>(outSidePipelineContext_);
pipelineContext_ = AceType::MakeRefPtr<PipelineContext>(std::move(window), taskExecutor_, assetManager_, nullptr, frontend_, instanceId_);
渲染卡片使用的是CardFrontend
- CardFrontend、CardEventHandler、CardFrontendDelegate、JsCardParser
卡片渲染引擎
流程分析
初始化流程
图 3 初始化时序图
- 首先前端创建FormComponent组件,并设置属性和回调。
- 然后ace框架在vsync事件里创建FormElement和RenderForm。
- FormElement初始化创建FormManagerDelegate,并注册事件回调。
- FormElement在update事件中创建SubContainer,然后通过FormManagerDelegate通知卡片管理者。
- RouterEvent只在lite系统使用,本文档后面不做分析了
管理中心发起事件流程
图 4 加载成功时序图
图 5 数据更新时序图
- 卡片数据更新由管理者回调通知,如果是首次则是Acquire流程,否则是Update流程。
- Acquire流程先将事件逐级回调通到应用js中,然后SubContainer调用CardFrontend展示卡片。
- Update流程只需要SubContainer调用CardFrontend更新卡片。
图 6 卸载时序图
- 卸载事件是通知应用的,应用在回调里可以将FormComponent去掉。
图 7 提供者ability退出时序图
- 这个事件我的理解是提供者ability挂掉了,但是使用这这里继续使用,通知管理者重新启动起来。
交互事件流程
图 8 交互事件时序图
- 卡片加载时,SubContainer在runcard方法中,向pipeline注册回调。
- pipeline响应到事件,回调SubContainer的方法。SubContainer回调FormElement,FormElement通过FormManagerDelegate发送给卡片管理者。
- 事件只支持router和message两种类型。
- router事件多一步调用pipeline的OnActionEvent。
- 最终提供者ability响应事件。提供者是一个FormExtension的子类ability,在方法onEvent(formId, message)中处理事件。
- 与其他控件的最大区别就是,UI及UI事件代码和事件响应代码在两个位置,并运行于两个ability中。
总结
本文主要介绍了FormComponent控件的关键实现机制、主要类关系及重要的处理流程,侧重于改控件本身,如果需要更完整的卡片原子服务流程,还需要分析卡片管理者FormMgr。两者联系起来学习,才能更清楚的理解完整的流程。
更多原创内容请关注:深开鸿技术团队
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建OpenHarmony生态。
大佬图片有点看不清,方便传份到附件中吗
同求.................