龙空技术网

深入理解 ArkUI - 框架初始化

一两风 284

前言:

现时大家对“js绑定不上初始化属性”可能比较注重,你们都需要分析一些“js绑定不上初始化属性”的相关知识。那么小编同时在网络上搜集了一些关于“js绑定不上初始化属性””的相关知识,希望你们能喜欢,朋友们快快来学习一下吧!

深入理解 ArkUI - 框架初始化从Stage模型说起

Stage模型应用程序中的 UIAbility 实例会以不同的状态传输。UIAbility 类提供一系列回调。通过这些回调,可以了解 UIAbility 实例的状态变化。

UIAbility的生命周期有创建、前台、后台、销毁四种状态

UIAbility实例创建完成后,在进入Foreground状态之前,系统会创建一个WindowStage实例,并触发onWindowStageCreate回调。您可以在回调中设置 UI 加载和 WindowStage 事件订阅。

使用DevEco创建简单Demo,src/main/ets/entryability/EntryAbility.ts代码中定义了onWindowStageCreate函数

export default class EntryAbility extends UIAbility {  ...  onWindowStageCreate(windowStage: window.WindowStage) {    // Main window is created, set main page for this ability    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');    windowStage.loadContent('pages/Index', (err, data) => {      if (err.code) {        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');        return;      }      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');    });  }  ...}

启动过程UIAbility::OnForeground过程中会创建AppWindowStage,回调onWindowStageCreate函数,通过windowStage.loadContent函数完成ArkUI初始化和页面加载。

loadContent函数实现在文件foundation/window/window_manager/interfaces/kits/napi/window_runtime/window_stage_napi/js_window_stage.cpp

napi_value JsWindowStage::OnLoadContent(napi_env env, napi_callback_info info, bool isLoadedByName){    ...    // 创建LoadContentTask异步Napi任务    NapiAsyncTask::CompleteCallback complete =        [weak = windowScene_, contentStorage, contextUrl, isLoadedByName](            napi_env env, NapiAsyncTask& task, int32_t status) {            auto weakScene = weak.lock();            sptr<Window> win = weakScene ? weakScene->GetMainWindow() : nullptr;            if (win == nullptr) {                task.Reject(env, CreateJsError(env, static_cast<int32_t>(WmErrorCode::WM_ERROR_STATE_ABNORMALLY)));                WLOGFE("[NAPI]Get window failed");                return;            }            LoadContentTask(contentStorage, contextUrl, win, env, task, isLoadedByName);        };    napi_value result = nullptr;    NapiAsyncTask::Schedule("JsWindowStage::OnLoadContent",        env, CreateAsyncTaskWithLastParam(env, callBack, nullptr, std::move(complete), &result));    return result;}

LoadContentTask中创建UiContent并初始化ArkUI框架。

WMError WindowSessionImpl::SetUIContentInner(const std::string& contentInfo, napi_env env, napi_value storage,    WindowSetUIContentType type, AppExecFwk::Ability* ability){    ...    switch (type) {        default:        case WindowSetUIContentType::DEFAULT:            aceRet = uiContent->Initialize(this, contentInfo, storage);            break;        ...    }    ...}
初始化

整个流程图如下所示:

涉及到数据结构如下所示:

Container初始化

如时序图Container初始化所示

1. AceContainer::CreateContainer创建AceContainer对象,并在构造函数完成JS线程的创建保存在jsEunner_

2. 创建JsFrontend对象,作为ArkUI框架从后端到前端的唯一入口,与AceAbility、AceCntainer一一对应。

3. 当前主要是响应式框架,根据类型FrontendType::DECLARATIVE_JS创建DeclarativeFrontendNG

4. 动态创建jsEnginedeclarativeFrontend绑定

Pipeline初始化

如时序图Pipeline初始化所示

VSync注册

AceContainer::SetView函数会创建RosenWindow,构造函数如下:

RosenWindow::RosenWindow(const OHOS::sptr<OHOS::Rosen::Window>& window, RefPtr<TaskExecutor> taskExecutor, int32_t id)    : rsWindow_(window), taskExecutor_(taskExecutor), id_(id){    vsyncCallback_ = std::make_shared<OHOS::Rosen::VsyncCallback>();    vsyncCallback_->onCallback = [weakTask = taskExecutor_, id = id_](int64_t timeStampNanos, int64_t frameCount) {        auto taskExecutor = weakTask.Upgrade();        auto onVsync = [id, timeStampNanos, frameCount] {            int64_t ts = GetSysTimestamp();            ArkUIPerfMonitor::GetInstance().StartPerf();            if (FrameReport::GetInstance().GetEnable()) {                FrameReport::GetInstance().FlushBegin();            }            ContainerScope scope(id);            // use container to get window can make sure the window is valid            auto container = Container::Current();            CHECK_NULL_VOID(container);            auto window = container->GetWindow();            CHECK_NULL_VOID(window);            int64_t refreshPeriod = window->GetVSyncPeriod();            window->OnVsync(static_cast<uint64_t>(timeStampNanos), static_cast<uint64_t>(frameCount));            ArkUIPerfMonitor::GetInstance().FinishPerf();            auto pipeline = container->GetPipelineContext();            CHECK_NULL_VOID(pipeline);            pipeline->OnIdle(std::min(ts, timeStampNanos) + refreshPeriod);            JankFrameReport::GetInstance().JankFrameRecord(timeStampNanos, window->GetWindowName());            if (FrameReport::GetInstance().GetEnable()) {                FrameReport::GetInstance().FlushEnd();            }            window->SetLastVsyncEndTimestamp(GetSysTimestamp());        };        auto uiTaskRunner = SingleTaskExecutor::Make(taskExecutor, TaskExecutor::TaskType::UI);        if (uiTaskRunner.IsRunOnCurrentThread()) {            onVsync();            return;        }        uiTaskRunner.PostTask([callback = std::move(onVsync)]() { callback(); }, "ArkUIRosenWindowVsync");    };    rsUIDirector_ = OHOS::Rosen::RSUIDirector::Create();    if (window->GetSurfaceNode()) {        rsUIDirector_->SetRSSurfaceNode(window->GetSurfaceNode());    }    rsUIDirector_->SetCacheDir(AceApplicationInfo::GetInstance().GetDataFileDirPath());    rsUIDirector_->Init();    rsUIDirector_->SetUITaskRunner(        [taskExecutor, id](const std::function<void()>& task, uint32_t delay) {            ContainerScope scope(id);            CHECK_NULL_VOID(taskExecutor);            taskExecutor->PostDelayedTask(                task, TaskExecutor::TaskType::UI, delay, "ArkUIRosenWindowRenderServiceTask", PriorityType::HIGH);        },        id);    rsUIDirector_->SetRequestVsyncCallback([weak = weak_from_this()]() {        auto self = weak.lock();        CHECK_NULL_VOID(self);        self->RequestFrame();    });}

vsyncCallback_就是ArkUI收到Vsync信号后要执行的逻辑:1. window->OnVsync(渲染管线执行)2.pipeline->OnIdle

ArkUI通过函数rsWindow_->RequestVsync(vsyncCallback_)向RS注册Vsync。下次Vsync信号到来时,RS通过此vsyncCallback_分发执行任务

Index页面加载

如时序图Page加载所示先创建Index页面,再OnPageReady中执行Build函数,创建页面组件。最终完成页面的加载

组件树创建

void AceContainer::AttachView(    std::shared_ptr<Window> window, AceViewPreview* view, double density, int32_t width, int32_t height){    ...    taskExecutor_->PostTask(        [weak]() {            auto context = weak.Upgrade();            if (context == nullptr) {                return;            }            context->SetupRootElement();        },        TaskExecutor::TaskType::UI);    aceView_->Launch();    ...}
void AceContainer::AttachView(    std::shared_ptr<Window> window, AceViewPreview* view, double density, int32_t width, int32_t height){    ...    taskExecutor_->PostTask(        [weak]() {            auto context = weak.Upgrade();            if (context == nullptr) {                return;            }            context->SetupRootElement();        },        TaskExecutor::TaskType::UI);    aceView_->Launch();    ...}
1. stageNode挂载在rootNode_
void PipelineContext::SetupRootElement(){    CHECK_RUN_ON(UI);    rootNode_ = FrameNode::CreateFrameNodeWithTree(        V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());    ...    auto stageNode = FrameNode::CreateFrameNode(        V2::STAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<StagePattern>());    ...    if (windowModal_ == WindowModal::CONTAINER_MODAL) {        ACE_SCOPED_TRACE("WindowModal::CONTAINER_MODAL");        MaximizeMode maximizeMode = GetWindowManager()->GetWindowMaximizeMode();        rootNode_->AddChild(            ContainerModalViewFactory::GetView(atomicService ? atomicService : stageNode, maximizeMode));    } else {        rootNode_->AddChild(atomicService ? atomicService : stageNode);    }    stageManager_ = MakeRefPtr<StageManager>(stageNode); //保存在stageManager_}
1. pageNode挂载在stageNode
void PageRouterManager::LoadPage(int32_t pageId, const RouterPageInfo& target, bool needHideLast, bool needTransition){    ...    auto pageNode =        FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), pagePattern);    ...    // loadNamedRouter_ == JsiDeclarativeEngine::LoadNamedRouterSource    auto result = loadNamedRouter_(target.url, target.isNamedRouterMode);    ...    if (!OnPageReady(pageNode, needHideLast, needTransition)) {        pageRouterStack_.pop_back();        LOGE("LoadPage OnPageReady Failed");        return;    }    ...}bool PageRouterManager::OnPageReady(    const RefPtr<FrameNode>& pageNode, bool needHideLast, bool needTransition, bool isCardRouter, int64_t cardId){    ...    auto context = DynamicCast<NG::PipelineContext>(pipeline);    auto stageManager = context ? context->GetStageManager() : nullptr; //取出stageNode    if (stageManager) {        return stageManager->PushPage(pageNode, needHideLast, needTransition);    }    return false;}
1. pageRootNodeIndex组件)挂载在pageNode
bool JsiDeclarativeEngine::LoadNamedRouterSource(const std::string& namedRoute, bool isTriggeredByJs){    ...    // 执行 new Index() 创建View    auto ret = iter->second.pageGenerator->Call(vm, JSNApi::GetGlobalObject(vm), argv.data(), 0);    if (!ret->IsObject()) {        return false;    }    // view 挂载到 pageNode 中    Framework::UpdateRootComponent(ret->ToObject(vm));    JSViewStackProcessor::JsStopGetAccessRecording();    return true;}

最终执行到UpdateRootComponent函数中将pageRootNode添加到pageNode

void UpdateRootComponent(const panda::Local<panda::ObjectRef>& obj){    ACE_FUNCTION_TRACE();    auto* view = static_cast<JSView*>(obj->GetNativePointerField(0));    ...        {            auto frontEnd = AceType::DynamicCast<DeclarativeFrontendNG>(container->GetFrontend());            CHECK_NULL_VOID(frontEnd);            auto pageRouterManager = frontEnd->GetPageRouterManager();            CHECK_NULL_VOID(pageRouterManager);            pageNode = pageRouterManager->GetCurrentPageNode();            CHECK_NULL_VOID(pageNode);        }        auto pageRootNode = AceType::DynamicCast<NG::UINode>(view->CreateViewNode());        CHECK_NULL_VOID(pageRootNode);        // root custom component        pageRootNode->MountToParent(pageNode);        ...    }

最终生成组件树

标签: #js绑定不上初始化属性