flutter窗口初始和繪制流程詳析
前言
環(huán)境: flutter sdk v1.7.8+hotfix.3@stable
對(duì)應(yīng) flutter engine: 54ad777f
這里關(guān)注的是C++層面的繪制流程,平臺(tái)怎樣驅(qū)動(dòng)和響應(yīng)繪制與渲染的過(guò)程,并不是Dart部分的渲染。
結(jié)合之前的分析,在虛擬機(jī)實(shí)例的構(gòu)造函數(shù)中調(diào)用了一個(gè)重要方法DartUI::InitForGlobal()
, 調(diào)用流程再羅列一下:
DartVMRef::Create DartVMRef::DartVMRef DartVM::Create DartVMData::Create DartVM::DartVM DartUI::InitForGlobal()
實(shí)現(xiàn)體很明了,注冊(cè)了各種類對(duì)象的方法,也就是說(shuō),這些在dart語(yǔ)言繼承NativeFieldWrapperClass2的類都有一份在C++層的實(shí)現(xiàn),也說(shuō)明了DartSDK是如何提供接口綁定與C++層的實(shí)現(xiàn),相當(dāng)于java語(yǔ)言中的jni。
另外還有針對(duì)Isolate的初始化,不過(guò)只是設(shè)置了一個(gè)可以import的路徑,并不重要:
DartIsolate::CreateRootIsolate DartIsolate::CreateDartVMAndEmbedderObjectPair DartIsolate::LoadLibraries DartUI::InitForIsolate Dart_SetNativeResolver
視口設(shè)置
我們知道RuntimeController持有一個(gè)Window實(shí)例,看Window實(shí)例被創(chuàng)建之后做了哪些制作:
RuntimeController::RuntimeController Window::Window DartIsolate::CreateRootIsolate DartIsolate::DartIsolate DartIsolate::SetWindow => UIDartState::SetWindow WindowClient::UpdateIsolateDescription => RuntimeController::UpdateIsolateDescription RuntimeDelegate::UpdateIsolateDescription => Shell::UpdateIsolateDescription ServiceProtocol::SetHandlerDescription Window::DidCreateIsolate library_.Set("dart:ui") RuntimeController::FlushRuntimeStateToIsolate RuntimeController::SetViewportMetrics Window::UpdateWindowMetrics library_, _updateWindowMetrics
操作從最里層的Window一直傳遞到了Shell,最重要的一個(gè)作用是初始化了ViewPort(視口:用作畫布的大小,分辨率等尺寸信息),再跟一下ViewPort被初始化后又如何被設(shè)置的:
FlutterView.onSizeChanged FlutterView.updateViewportMetrics FlutterJNI.setViewportMetrics FlutterJNI.nativeSetViewportMetrics ::SetViewportMetrics AndroidShellHolder::SetViewportMetrics [async:ui]Engine::SetViewportMetrics RuntimeController::SetViewportMetrics Window::UpdateWindowMetrics Engine::ScheduleFrame
這里從Java調(diào)用到C++,FlutterView.onSizeChanged
這個(gè)操作是在FlutterView實(shí)例創(chuàng)建之后被系統(tǒng)調(diào)用的(而FlutterView的創(chuàng)建發(fā)生在Activity.onCreate時(shí)機(jī)),顯然是響應(yīng)平臺(tái)層的通知,這符合我們的認(rèn)知預(yù)期,因?yàn)楫嫴嫉拇笮】赡芤驗(yàn)橛脩舨僮靼l(fā)生變化,dart層需要被動(dòng)響應(yīng)。
需要注意的是響應(yīng)onSizeChanged在Platform線程,調(diào)用Engine::SetViewportMetrics
切到了UI線程,銘記Engine的所有的操作都是在UI線程。
啟動(dòng)畫幀
Engine在通過(guò)RuntimeController設(shè)置了窗口的尺寸之后,調(diào)用了另一個(gè)重要方法ScheduleFrame,于是看它的實(shí)現(xiàn):
Engine::ScheduleFrame Animator::RequestFrame [async:ui]Animator::AwaitVSync VsyncWaiter::AsyncWaitForVsync callback_= {Animator::BeginFrame} VsyncWaiter::AwaitVSync => VsyncWaiterAndroid::AwaitVSync [async:platform]FlutterJNI.asyncWaitForVsync AsyncWaitForVsyncDelegate.asyncWaitForVsync => VsyncWaiter.asyncWaitForVsyncDelegate Choreographer.getInstance().postFrameCallback Delegate::OnAnimatorNotifyIdle => Shell::OnAnimatorNotifyIdle Engine::NotifyIdle
通知VSync
這里操作有些凌亂,首先切到UI線程,又切到Platform線程,其實(shí)就是為了調(diào)用平臺(tái)接口,搞清這個(gè)最終目的。
終于涉及到了繪制圖像所需要的關(guān)鍵類Animator 和VSyncWaiter :
- 在UI線程等待VSync信號(hào),表示信號(hào)到達(dá)后執(zhí)行
Animator::BeginFrame
方法; - 如何設(shè)置VSync信號(hào)?通過(guò)調(diào)用平臺(tái)接口,平臺(tái)操作必須都在Platform線程,于是從UI線程切到Platform線程,目的是去調(diào)用android的
Choreographer.postFrameCallback
,這樣又執(zhí)行了一串從C++調(diào)到j(luò)ava的過(guò)程。
響應(yīng)VSync
因?yàn)槭窃趈ava層調(diào)用的VSync回調(diào),只能先在Java層響應(yīng)于是有:
FrameCallback.doFrame <= VsyncWaiter.asyncWaitForVsyncDelegate FlutterJNI.nativeOnVsync VsyncWaiterAndroid::OnNativeVsync VsyncWaiterAndroid::ConsumePendingCallback VsyncWaiter::FireCallback [async:ui]callback() => Animator::BeginFrame
在VSync信號(hào)到達(dá)之后,最終在UI線程響應(yīng)了Animator::BeginFrame,且看其實(shí)現(xiàn):
Animator::BeginFrame Animator::Delegate::OnAnimatorBeginFrame => Shell:: Engine::BeginFrame Window::BeginFrame library_."_beginFrame" => hooks.dart:_beginFrame UIDartState::FlushMicrotasksNow tonic::DartMicrotaskQueue::RunMicrotasks library_."_drawFrame" => hooks.dart:_drawFrame
最終的最終回到了dart層,并調(diào)用了其兩個(gè)重要方法:_beginFrame和_drawFrame,完成了幀的繪制。
VSync創(chuàng)建
另外羅列一下VSyncWaiter創(chuàng)建時(shí)機(jī):
Shell::CreateShellOnPlatformThread PlatformView::CreateVSyncWaiter => PlatformViewAndroid::CreateVSyncWaiter VsyncWaiterAndroid() Animator::Animator Engine::Engine
它是與創(chuàng)建Shell同樣的時(shí)機(jī),也就是說(shuō)在Platform線程由PlatformView::CreateVSyncWaiter
創(chuàng)建的,并被Animator持有,而Animator又是被Engine持有。VSyncWaiter與Engine一樣,所有的操作都必須在UI線程中執(zhí)行
窗口渲染
窗口的渲染是由Dart層的Window完成的,其實(shí)調(diào)用了C++層的實(shí)現(xiàn):
("Window_render", Render) Render() (window.cc:30) Scene= WindowClient::Render Scene::takeLayerTree RuntimeDelegate::Render => Engine::Render ProducerContinuation::Complete(layer_tree) Animator::Delegate::OnAnimatorDraw => Shell::OnAnimatorDraw(layer_tree_pipeline_) [async:gpu]Rasterizer::Draw => android_shell_holder.cc:76 Rasterizer::DoDraw Rasterizer::DrawToSurface Surface::AcquireFrame ExternalViewEmbedder::BeginFrame CompositorContext::AcquireFrame ScopedFrame::Raster SurfaceFrame::Submit ExternalViewEmbedder::SubmitFrame FireNextFrameCallbackIfPresent Rasterizer::Delegate::OnFrameRasterized "Window_scheduleFrame", ScheduleFrame
這里涉及的對(duì)象更多了,而且緊密的與Dart層的繪制與渲染機(jī)制關(guān)聯(lián)。值得注意的是具體的繪制操作(光柵化)是在GPU線程進(jìn)行。
另外Dart層的Window也需要主動(dòng)的調(diào)度幀,因此也綁定了ScheduleFrame方法。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Android中的指紋識(shí)別demo開發(fā)實(shí)例
這篇文章主要介紹了Android中的指紋識(shí)別demo開發(fā)實(shí)例的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09FrameLayout和Fragment處理Android應(yīng)用UI布局實(shí)例
這篇文章主要介紹了FrameLayout和Fragment處理Android應(yīng)用UI布局實(shí)例,安卓3.0以后Fragment的出現(xiàn)為多尺寸屏幕的適配帶來(lái)了方便,需要的朋友可以參考下2016-02-02Android view自定義實(shí)現(xiàn)動(dòng)態(tài)進(jìn)度條
這篇文章主要介紹了Android view自定義實(shí)現(xiàn)動(dòng)態(tài)進(jìn)度條的相關(guān)資料,這里提供實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-12-12Android?Flutter使用本地?cái)?shù)據(jù)庫(kù)編寫備忘錄應(yīng)用
這篇文章主要為大家詳細(xì)介紹了Android?Flutter如何使用本地?cái)?shù)據(jù)庫(kù)實(shí)現(xiàn)編寫簡(jiǎn)單的備忘錄應(yīng)用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-03-03Android學(xué)習(xí)筆記——Menu介紹(二)
這次將繼續(xù)上一篇文章沒(méi)有講完的Menu的學(xué)習(xí),上下文菜單(Context menu)和彈出菜單(Popup menu)2014-10-10Android自定義View制作動(dòng)態(tài)炫酷按鈕實(shí)例解析
這篇文章主要為大家詳細(xì)解析了Android自定義View制作動(dòng)態(tài)炫酷按鈕實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07Android studio中生成引用.aar和.jar的方法詳解
這篇文章主要是講解.aar的生成與引用,文中的內(nèi)容屬于完全基礎(chǔ)性概念,對(duì)剛學(xué)習(xí)使用Android studio的朋友們很有幫助,有需要的可以參考學(xué)習(xí),下面來(lái)一起看看吧。2016-09-09安卓(Android)實(shí)現(xiàn)選擇時(shí)間功能
安卓開發(fā)過(guò)程中難免會(huì)碰到需要選擇日期時(shí)間的情況,當(dāng)然不可能讓用戶自己輸入日期時(shí)間,小編收集整理了一些資料,總結(jié)了一下如何實(shí)現(xiàn)android選擇時(shí)間的功能,方便后來(lái)者參考2016-08-08