flutter窗口初始和繪制流程詳析
前言
環(huán)境: flutter sdk v1.7.8+hotfix.3@stable
對應 flutter engine: 54ad777f
這里關注的是C++層面的繪制流程,平臺怎樣驅動和響應繪制與渲染的過程,并不是Dart部分的渲染。
結合之前的分析,在虛擬機實例的構造函數(shù)中調(diào)用了一個重要方法DartUI::InitForGlobal() , 調(diào)用流程再羅列一下:
DartVMRef::Create DartVMRef::DartVMRef DartVM::Create DartVMData::Create DartVM::DartVM DartUI::InitForGlobal()
實現(xiàn)體很明了,注冊了各種類對象的方法,也就是說,這些在dart語言繼承NativeFieldWrapperClass2的類都有一份在C++層的實現(xiàn),也說明了DartSDK是如何提供接口綁定與C++層的實現(xiàn),相當于java語言中的jni。
另外還有針對Isolate的初始化,不過只是設置了一個可以import的路徑,并不重要:
DartIsolate::CreateRootIsolate DartIsolate::CreateDartVMAndEmbedderObjectPair DartIsolate::LoadLibraries DartUI::InitForIsolate Dart_SetNativeResolver
視口設置
我們知道RuntimeController持有一個Window實例,看Window實例被創(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,最重要的一個作用是初始化了ViewPort(視口:用作畫布的大小,分辨率等尺寸信息),再跟一下ViewPort被初始化后又如何被設置的:
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這個操作是在FlutterView實例創(chuàng)建之后被系統(tǒng)調(diào)用的(而FlutterView的創(chuàng)建發(fā)生在Activity.onCreate時機),顯然是響應平臺層的通知,這符合我們的認知預期,因為畫布的大小可能因為用戶操作發(fā)生變化,dart層需要被動響應。
需要注意的是響應onSizeChanged在Platform線程,調(diào)用Engine::SetViewportMetrics切到了UI線程,銘記Engine的所有的操作都是在UI線程。
啟動畫幀
Engine在通過RuntimeController設置了窗口的尺寸之后,調(diào)用了另一個重要方法ScheduleFrame,于是看它的實現(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線程,其實就是為了調(diào)用平臺接口,搞清這個最終目的。
終于涉及到了繪制圖像所需要的關鍵類Animator 和VSyncWaiter :
- 在UI線程等待VSync信號,表示信號到達后執(zhí)行
Animator::BeginFrame方法; - 如何設置VSync信號?通過調(diào)用平臺接口,平臺操作必須都在Platform線程,于是從UI線程切到Platform線程,目的是去調(diào)用android的
Choreographer.postFrameCallback,這樣又執(zhí)行了一串從C++調(diào)到java的過程。
響應VSync
因為是在java層調(diào)用的VSync回調(diào),只能先在Java層響應于是有:
FrameCallback.doFrame <= VsyncWaiter.asyncWaitForVsyncDelegate FlutterJNI.nativeOnVsync VsyncWaiterAndroid::OnNativeVsync VsyncWaiterAndroid::ConsumePendingCallback VsyncWaiter::FireCallback [async:ui]callback() => Animator::BeginFrame
在VSync信號到達之后,最終在UI線程響應了Animator::BeginFrame,且看其實現(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)用了其兩個重要方法:_beginFrame和_drawFrame,完成了幀的繪制。
VSync創(chuàng)建
另外羅列一下VSyncWaiter創(chuàng)建時機:
Shell::CreateShellOnPlatformThread PlatformView::CreateVSyncWaiter => PlatformViewAndroid::CreateVSyncWaiter VsyncWaiterAndroid() Animator::Animator Engine::Engine
它是與創(chuàng)建Shell同樣的時機,也就是說在Platform線程由PlatformView::CreateVSyncWaiter創(chuàng)建的,并被Animator持有,而Animator又是被Engine持有。VSyncWaiter與Engine一樣,所有的操作都必須在UI線程中執(zhí)行
窗口渲染
窗口的渲染是由Dart層的Window完成的,其實調(diào)用了C++層的實現(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
這里涉及的對象更多了,而且緊密的與Dart層的繪制與渲染機制關聯(lián)。值得注意的是具體的繪制操作(光柵化)是在GPU線程進行。
另外Dart層的Window也需要主動的調(diào)度幀,因此也綁定了ScheduleFrame方法。
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。
相關文章
Android編程實現(xiàn)對電池狀態(tài)的監(jiān)視功能示例
這篇文章主要介紹了Android編程實現(xiàn)對電池狀態(tài)的監(jiān)視功能,涉及Android基于廣播實現(xiàn)針對電源電量的判定與監(jiān)視技巧,需要的朋友可以參考下2016-11-11
基于android示例程序(bitmapfun) 高效加載圖片讓人無語地方
嘗試了使用git上的一個開源項目afinal(bitmapfun的封裝版)來加載圖片,但是在測試的時候發(fā)現(xiàn)了一個問題,新的圖片加載器(bitmapfun)比之前用的ImageDownloader要慢很多,特別是在網(wǎng)絡狀況不好的時候,那簡直是太讓人無語了2013-04-04

