中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

flutter窗口初始和繪制的示例分析

發布時間:2021-05-19 11:21:19 來源:億速云 閱讀:112 作者:小新 欄目:移動開發

這篇文章主要介紹了flutter窗口初始和繪制的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

前言

環境: flutter sdk v1.7.8+hotfix.3@stable

對應 flutter engine: 54ad777f

這里關注的是C++層面的繪制流程,平臺怎樣驅動和響應繪制與渲染的過程,并不是Dart部分的渲染。

結合之前的分析,在虛擬機實例的構造函數中調用了一個重要方法DartUI::InitForGlobal() , 調用流程再羅列一下:

DartVMRef::Create
 DartVMRef::DartVMRef
 DartVM::Create
 DartVMData::Create
 DartVM::DartVM
  DartUI::InitForGlobal()

實現體很明了,注冊了各種類對象的方法,也就是說,這些在dart語言繼承NativeFieldWrapperClass2的類都有一份在C++層的實現,也說明了DartSDK是如何提供接口綁定與C++層的實現,相當于java語言中的jni。

另外還有針對Isolate的初始化,不過只是設置了一個可以import的路徑,并不重要:

DartIsolate::CreateRootIsolate
 DartIsolate::CreateDartVMAndEmbedderObjectPair
 DartIsolate::LoadLibraries
 DartUI::InitForIsolate
 Dart_SetNativeResolver

視口設置

我們知道RuntimeController持有一個Window實例,看Window實例被創建之后做了哪些制作:

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調用到C++,FlutterView.onSizeChanged這個操作是在FlutterView實例創建之后被系統調用的(而FlutterView的創建發生在Activity.onCreate時機),顯然是響應平臺層的通知,這符合我們的認知預期,因為畫布的大小可能因為用戶操作發生變化,dart層需要被動響應。

需要注意的是響應onSizeChanged在Platform線程,調用Engine::SetViewportMetrics切到了UI線程,銘記Engine的所有的操作都是在UI線程。

啟動畫幀

Engine在通過RuntimeController設置了窗口的尺寸之后,調用了另一個重要方法ScheduleFrame,于是看它的實現:

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線程,其實就是為了調用平臺接口,搞清這個最終目的。
終于涉及到了繪制圖像所需要的關鍵類Animator 和VSyncWaiter :

  1. 在UI線程等待VSync信號,表示信號到達后執行Animator::BeginFrame方法;

  2. 如何設置VSync信號?通過調用平臺接口,平臺操作必須都在Platform線程,于是從UI線程切到Platform線程,目的是去調用android的Choreographer.postFrameCallback,這樣又執行了一串從C++調到java的過程。

響應VSync

因為是在java層調用的VSync回調,只能先在Java層響應于是有:

FrameCallback.doFrame <= VsyncWaiter.asyncWaitForVsyncDelegate
 FlutterJNI.nativeOnVsync
 VsyncWaiterAndroid::OnNativeVsync
  VsyncWaiterAndroid::ConsumePendingCallback
 VsyncWaiter::FireCallback
  [async:ui]callback() => Animator::BeginFrame

在VSync信號到達之后,最終在UI線程響應了Animator::BeginFrame,且看其實現:

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層,并調用了其兩個重要方法:_beginFrame和_drawFrame,完成了幀的繪制。

VSync創建

另外羅列一下VSyncWaiter創建時機:

Shell::CreateShellOnPlatformThread
 PlatformView::CreateVSyncWaiter => PlatformViewAndroid::CreateVSyncWaiter
 VsyncWaiterAndroid()
 Animator::Animator
 Engine::Engine

它是與創建Shell同樣的時機,也就是說在Platform線程由PlatformView::CreateVSyncWaiter創建的,并被Animator持有,而Animator又是被Engine持有。VSyncWaiter與Engine一樣,所有的操作都必須在UI線程中執行

窗口渲染

窗口的渲染是由Dart層的Window完成的,其實調用了C++層的實現:

("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層的繪制與渲染機制關聯。值得注意的是具體的繪制操作(光柵化)是在GPU線程進行。

另外Dart層的Window也需要主動的調度幀,因此也綁定了ScheduleFrame方法。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“flutter窗口初始和繪制的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

湛江市| 拉萨市| 广南县| 苏尼特左旗| 莒南县| 靖宇县| 嘉荫县| 平定县| 色达县| 侯马市| 太康县| 连山| 东阿县| 黔南| 桃园市| 周宁县| 岚皋县| 凌源市| 彭州市| 延川县| 苗栗县| 兴安盟| 稷山县| 常州市| 东港市| 普陀区| 邹城市| 蓬溪县| 确山县| 平乡县| 广宗县| 民丰县| 沅江市| 富阳市| 桃园市| 米易县| 行唐县| 新竹市| 华安县| 祥云县| 合作市|