龙空技术网

深入理解 ArkUI - 组件生命周期

一两风 457

前言:

眼前大家对“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继承自ViewPUViewPU继承自PUV2ViewBasePUV2ViewBase继承自NativeViewPartialUpdateObscuredExample最终创建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初始化会注册生命周期绑定函数UpdateRootComponentpageRouterManager。当页面加载时,通过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,由于是自定义组件,这里的nodeCustomNode类型。3. 页面生命周期onPageShow触发4. 标脏请求Vsync,完成页面渲染

Render函数依次触发OnAppearBuildItemDidBuild生命周期回调.

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_这个桥梁执行到前端的aboutToDisappearaboutToBeDelete

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值变化都会触发非页面级组件的删除和重建。 删除:触发aboutToDisappearaboutToBeDelete 重建: 触发OnAppearBuildItemDidBuild生命周期回调

基础组件

当前基础组件的生命周期包含onAppearonDisAppearonAttachonDetach,通过属性的方式注册到后端的EventHub中保存。 当组件上树时触发onAttachonAppear

void FrameNode::OnAttachToMainTree(bool recursive){    TriggerRsProfilerNodeMountCallbackIfExist();    eventHub_->FireOnAttach();    eventHub_->FireOnAppear();    ...}

eventHub_->FireOnAttach在挂树后立即执行

void EventHub::FireOnAttach(){    if (onAttach_) {        auto onAttach = onAttach_;        onAttach();    }}

eventHub_->FireOnAppearVsync消息后执行

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");    }}

组件下树触发onDetachonDisAppear

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绑定事件