前言:
眼前大家对“viewbinding绑定事件”都比较关注,姐妹们都需要了解一些“viewbinding绑定事件”的相关文章。那么小编也在网摘上搜集了一些有关“viewbinding绑定事件””的相关内容,希望各位老铁们能喜欢,你们一起来学习一下吧!深入理解 ArkUI - 组件生命周期组件生命周期
官网对生命周期做了初步介绍. 生命周期流程如下图所示,下图展示的是被@Entry装饰的组件(页面)生命周期。
页面级组件(@Entry修饰)
创建新工程在编译文件build/default/cache/default/default@CompileArkTS/esmodule/debug/entry/src/main/ets/pages/Index.ts中通过registerNamedRoute(() => new ObscuredExample(undefined, {}), "", { bundleName: "com.ohos.test", moduleName: "entry", pagePath: "pages/Index", pageFullPath: "entry/src/main/ets/pages/Index", integratedHsp: "false" });函数创建根组件ObscuredExample。 组件继承关系:ObscuredExample继承自ViewPU,ViewPU继承自PUV2ViewBase,PUV2ViewBase继承自NativeViewPartialUpdate,ObscuredExample最终创建NativeViewPartialUpdate类型的对象。
前后端对象绑定
Ark虚拟机通过JSClass<JSViewPartialUpdate>::Declare("NativeViewPartialUpdate")将前端NativeViewPartialUpdate对象和后端JSViewPartialUpdate对象绑定。
frameworks/bridge/declarative_frontend/jsview/js_view.cppvoid JSViewPartialUpdate::JSBind(BindingTarget object){ JSClass<JSViewPartialUpdate>::Declare("NativeViewPartialUpdate"); MethodOptions opt = MethodOptions::NONE; JSClass<JSViewPartialUpdate>::StaticMethod("create", &JSViewPartialUpdate::Create, opt); JSClass<JSViewPartialUpdate>::StaticMethod("createRecycle", &JSViewPartialUpdate::CreateRecycle, opt); ... JSClass<JSViewPartialUpdate>::InheritAndBind<JSViewAbstract>(object, ConstructorCallback, DestructorCallback);}JSViewPartialUpdate对象与CustomNode对象绑定
后端的自定义组件是以CustomNode对象管理,如何绑定的?
创建后端JSViewPartialUpdate对象,并绑定ViewFunctions对象。ViewFunctions对象是后端调用前端函数的封装,其中包含组件生命周期回调。CreateViewNode函数通过view_partial_update_model_ng.cpp创建CustomNodeBase对象并建立与ViewFunctions的绑定关系。这样封装主要是为了拆分新老ArkUI框架。
RefPtr<AceType> ViewPartialUpdateModelNG::CreateNode(NodeInfoPU&& info){ // create component, return new something, need to set proper ID auto viewId = NG::ViewStackProcessor::GetInstance()->ClaimNodeId(); ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", info.jsViewName.c_str(), viewId); ... RefPtr<NG::CustomNodeBase> customNode; ... customNode = NG::CustomNode::CreateCustomNode(viewId, key); if (info.updateNodeFunc) { info.updateNodeFunc(customNode); } customNode->SetAppearFunction(std::move(info.appearFunc)); customNode->SetDidBuildFunction(std::move(info.didBuildFunc)); auto renderFunc = [renderFunction = std::move(info.renderFunc)]() -> RefPtr<UINode> { auto node = renderFunction(); return AceType::DynamicCast<UINode>(node); }; customNode->SetRenderFunction(std::move(renderFunc)); customNode->SetUpdateFunction(std::move(info.updateFunc)); customNode->SetDestroyFunction(std::move(info.removeFunc)); ... return customNode;}页面级组件生命周期绑定
AceContainer初始化会注册生命周期绑定函数UpdateRootComponent给pageRouterManager。当页面加载时,通过pageRouterManager将生命周期与PageNode绑定。
frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register_impl_ng.cppvoid UpdateRootComponent(const EcmaVM* vm, const panda::Local<panda::ObjectRef>& obj){ ... pageRootNode->MountToParent(pageNode); // update page life cycle function. auto pagePattern = pageNode->GetPattern<NG::PagePattern>(); CHECK_NULL_VOID(pagePattern); // Register RenderDone callback to jsView so that js view can notify pagePattern the render function has been // finish. The onPageShow life cycle must be after the InitialRender function execution. view->RegisterRenderDoneCallback([weak = AceType::WeakClaim(AceType::RawPtr(pagePattern))]() { auto pagePattern = weak.Upgrade(); CHECK_NULL_VOID(pagePattern); pagePattern->MarkRenderDone(); }); pagePattern->SetOnPageShow([weak = Referenced::WeakClaim(view)]() { auto view = weak.Upgrade(); if (view) { view->FireOnShow(); } }); pagePattern->SetOnPageHide([weak = Referenced::WeakClaim(view)]() { auto view = weak.Upgrade(); if (view) { view->FireOnHide(); } }); pagePattern->SetOnBackPressed([weak = Referenced::WeakClaim(view)]() { auto view = weak.Upgrade(); if (view) { return view->FireOnBackPress(); } return false; }); auto customNode = AceType::DynamicCast<NG::CustomNodeBase>(pageRootNode); pagePattern->SetPageTransitionFunc( [weakCustom = WeakPtr<NG::CustomNodeBase>(customNode), weakPage = WeakPtr<NG::FrameNode>(pageNode)]() { auto custom = weakCustom.Upgrade(); auto page = weakPage.Upgrade(); if (custom && page) { NG::ScopedViewStackProcessor scopedViewStackProcessor; NG::ViewStackProcessor::GetInstance()->SetPageNode(page); custom->CallPageTransitionFunction(); NG::ViewStackProcessor::GetInstance()->SetPageNode(nullptr); } });}aboutToAppear、build、onDidBuild
前文已经分析首页通过页面组件通过router.pushUrl方式加载,主要流程在StageManager::PushPage函数。
frameworks/core/components_ng/pattern/stage/stage_manager.cppbool StageManager::PushPage(const RefPtr<FrameNode>& node, bool needHideLast, bool needTransition){ ... // mount to parent and mark build render tree. node->MountToParent(stageNode_); // then build the total child. Build will trigger page create and onAboutToAppear node->Build(nullptr); // fire new lifecycle if (hidePageNode && needHideLast && isNewLifecycle) { FirePageHide(hidePageNode, needTransition ? PageTransitionType::EXIT_PUSH : PageTransitionType::NONE); } stageNode_->RebuildRenderContextTree(); FirePageShow(node, needTransition ? ... stageNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); return true;}1. 通过MountToParent构建组件父子依赖,前文已讲述。2. 组件Build,由于是自定义组件,这里的node是CustomNode类型。3. 页面生命周期onPageShow触发4. 标脏请求Vsync,完成页面渲染
Render函数依次触发OnAppear、BuildItem、DidBuild生命周期回调.
void CustomNode::Render(){ // NOTE: this function will be re-enter, we need backup needMarkParent_ first and restore it later. bool needMarkParentBak = needMarkParent_; needMarkParent_ = false; if (renderFunction_) { RenderFunction renderFunction = nullptr; std::swap(renderFunction, renderFunction_); { ACE_SCOPED_TRACE("CustomNode:OnAppear"); FireOnAppear(); } { COMPONENT_CREATION_DURATION(); ACE_SCOPED_TRACE("CustomNode:BuildItem [%s][self:%d][parent:%d]", GetJSViewName().c_str(), GetId(), GetParent() ? GetParent()->GetId() : 0); // first create child node and wrapper. ScopedViewStackProcessor scopedViewStackProcessor; auto parent = GetParent(); bool parentNeedExportTexture = parent ? parent->IsNeedExportTexture() : false; ViewStackProcessor::GetInstance()->SetIsExportTexture(parentNeedExportTexture || IsNeedExportTexture()); auto child = renderFunction(); if (child) { child->MountToParent(Claim(this)); } } { ACE_SCOPED_TRACE("CustomNode::DidBuild"); FireDidBuild(); } } { FireRecycleRenderFunc(); } needMarkParent_ = needMarkParentBak;}onPageShow
组件创建完成后在FirePageShow函数触发页面OnPageShow。
onPageHide
当页面且后台,切换等操作触发页面OnPageHide
frameworks/core/components_ng/pattern/stage/stage_manager.cppbool StageManager::PopPage(const RefPtr<FrameNode>& inPage, bool needShowNext, bool needTransition){ ... FirePageHide(pageNode, needTransition ? PageTransitionType::EXIT_POP : PageTransitionType::NONE); ... stageNode_->RemoveChild(pageNode); pipeline->RequestFrame(); return true;}aboutToDisapear、aboutToDestory
stageNode_->RemoveChild会将组件从组件树移除然后组件析构。自定义组件在后端是CustomNode对象继承自CustomNodeBase。
CustomNodeBase::~CustomNodeBase(){ RecycleManager::Erase(recycleInfo_.elemtId); // appearFunc_ & destroyFunc_ should be executed in pairs if (!executeFireOnAppear_ && appearFunc_) { appearFunc_(); if (didBuildFunc_) { didBuildFunc_(); } } if (destroyFunc_) { ACE_SCOPED_TRACE("CustomNodeBase:Destroy [%s]", GetJSViewName().c_str()); destroyFunc_(); }}
destroyFunc_函数与removeFunction函数绑定
auto removeFunction = [weak = AceType::WeakClaim(this)]() -> void { auto jsView = weak.Upgrade(); CHECK_NULL_VOID(jsView); ContainerScope scope(jsView->GetInstanceId()); jsView->Destroy(nullptr); jsView->viewNode_.Reset();};
最终借助jsViewFunction_这个桥梁执行到前端的aboutToDisappear和aboutToBeDelete。
void JSViewPartialUpdate::Destroy(JSView* parentCustomView){ if (jsViewFunction_ == nullptr) { // already called Destroy before return; } { ACE_SCORING_EVENT("Component[" + viewId_ + "].Disappear"); jsViewFunction_->ExecuteDisappear(); } { ACE_SCORING_EVENT("Component[" + viewId_ + "].AboutToBeDeleted"); jsViewFunction_->ExecuteAboutToBeDeleted(); } pendingUpdateTasks_.clear(); jsViewFunction_->Destroy(); jsViewFunction_.Reset(); // release reference to JS view object, and allow GC, calls DestructorCallback jsViewObject_.Reset();}
详细流程图如下:
自定义组件(@Component修饰)
除了上述通过应用启动、router.pushUrl等方式触发页面加载,If分支切换、ForEach数组变更、LazyForEach触发的预加载或者Key值变化都会触发非页面级组件的删除和重建。 删除:触发aboutToDisappear、aboutToBeDelete 重建: 触发OnAppear、BuildItem、DidBuild生命周期回调
基础组件
当前基础组件的生命周期包含onAppear、onDisAppear、onAttach、onDetach,通过属性的方式注册到后端的EventHub中保存。 当组件上树时触发onAttach、onAppear。
void FrameNode::OnAttachToMainTree(bool recursive){ TriggerRsProfilerNodeMountCallbackIfExist(); eventHub_->FireOnAttach(); eventHub_->FireOnAppear(); ...}
eventHub_->FireOnAttach在挂树后立即执行
void EventHub::FireOnAttach(){ if (onAttach_) { auto onAttach = onAttach_; onAttach(); }}
eventHub_->FireOnAppear在Vsync消息后执行
void EventHub::FireOnAppear(){ if (onAppear_ || onJSFrameNodeAppear_) { auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck(); CHECK_NULL_VOID(pipeline); auto taskScheduler = pipeline->GetTaskExecutor(); CHECK_NULL_VOID(taskScheduler); taskScheduler->PostTask( [weak = WeakClaim(this)]() { auto eventHub = weak.Upgrade(); CHECK_NULL_VOID(eventHub); if (eventHub->onAppear_) { // callback may be overwritten in its invoke so we copy it first auto onAppear = eventHub->onAppear_; onAppear(); } if (eventHub->onJSFrameNodeAppear_) { // callback may be overwritten in its invoke so we copy it first auto onJSFrameNodeAppear = eventHub->onJSFrameNodeAppear_; onJSFrameNodeAppear(); } }, TaskExecutor::TaskType::UI, "ArkUIFrameNodeAppearEvent"); }}
组件下树触发onDetach、onDisAppear。
void FrameNode::OnDetachFromMainTree(bool recursive, PipelineContext* context){ ... eventHub_->OnDetachClear(); ...}void EventHub::OnDetachClear(){ FireOnDetach(); FireOnDisappear(); ClearStateStyle();}
FireOnDetach在下树后立即执行
void EventHub::FireOnDetach(){ if (onDetach_) { auto onDetach = onDetach_; onDetach(); }}
FireOnDisappear在下树后立即执行
void EventHub::FireOnDisappear(){ if (onDisappear_) { // callback may be overwritten in its invoke so we copy it first auto onDisappear = onDisappear_; onDisappear(); } if (onJSFrameNodeDisappear_) { // callback may be overwritten in its invoke so we copy it first auto onJSFrameNodeDisappear = onJSFrameNodeDisappear_; onJSFrameNodeDisappear(); }}总结
写个实例测试下,依次执行启动,点击Button按钮,且后台,执行结果如下:
@Entry@Componentstruct ObscuredExample { onPageShow(): void { console.log("LifeCycle Entry onPageShow"); } aboutToAppear(): void { console.log("LifeCycle Entry aboutToAppear"); } aboutToDisappear(): void { console.log("LifeCycle Entry aboutToDisappear"); } onPageHide(): void { console.log("LifeCycle Entry onPageHide"); } @State isShow: boolean = true build() { Row() { Column() { Button() .onClick(() => { this.isShow = !this.isShow }) if (this.isShow) { My() .width('100%') .height('100%') .onAppear(() => { console.log("LifeCycle Component onAppear"); }) .onAttach(() => { console.log("LifeCycle Component onAttach"); }) .onDetach(() => { console.log("LifeCycle Component onDetach"); }) .onDisAppear(() => { console.log("LifeCycle Component onDisAppear"); }) } } .width('100%') } .height('100%') }}
标签: #viewbinding绑定事件