Flutter基礎專題

Flutter專題

對比:
WebView:   優點:豐富的控件庫、動態化、良好的技術社區、測試自動化等等    
           缺點:渲染效率和java的執行能力比較差,頁面的加載速度和用戶體驗都不盡如人意

RN: 使用類HTML+JS的UI創建邏輯,生成對應的原生頁面,講頁面的渲染工作交給了系統,以渲染效率有很大優勢。但由於RN代碼通過JS橋接的方式轉換爲原生控件,所以安卓/iOS系統間的差異影響非常大,對應各個平臺的適配很麻煩。

爲啥flutter
Flutter: 開源跨平臺 UI 框架 Flutter。
        重寫了一套跨平臺的UI框架,渲染引擎是依靠Skia*圖形庫實現。  Flutter中的控件樹直接由渲染引擎和高性能本地ARM*代碼直接繪製,不需要通過中間對象(Web應用中的虛擬DOM和真實DOM,原生App中的虛擬控件和平臺控件)來繪製,是它有接近原生頁面的性能,幫助我們提供更好的用戶體驗。
        同時支持JIT和AOT*編譯。JIT編譯方式使其在開發階段可以--熱重載,在開發時省去的構建過程,提高開發效率。而在Release運行時採用AOT的編譯方式,使執行效率非常高,讓Release版本發揮更好的性能。

        //Skia 是一個 Google 開源的 C++ 二維圖形庫,提供各種常用的API,並可在多種軟硬件平臺上運行。Skia是一個完整的2D圖像庫,包括圖像、動畫、文本繪製功能
// Skia是跨平臺的,所以可以被嵌入到 Flutter的 iOS SDK中,而不用去研究 iOS閉源的 Core Graphics / Core Animation。
        //ARM 成熟的 架構 是處理器
        //AOT ((Ahead-Of-Time - 預先編譯)它們必須在執行前編譯成機器碼,  在android裏面,jit會把程序實時編譯爲機器字節碼,然後虛擬機讀取,打開程序

flutter架構和實現原理
1、Flutter 使用Dart語言。
    1)Dart一般情況下是運行在DartVM上,但是也可以編譯爲ARM代碼直接運行在硬件上,考慮一下與其它硬件的結合。
    2)Dart支持AOT和JIT兩種編譯方式。
    3)Dart可以利用獨特的隔離區(Isolate)實現多線程。而且不共享內存,可實現無鎖快速分配。
    4)分代垃圾回收,非常適合 UI 框架中常見的大量 Widgets 對象創建和銷燬的優化。
    5)在爲創建的對象分配內存時,Dart是在現有的堆上移動指針,保證內存的增長是線性的,省了查找可用內存的過程

Flutter架構也是採用的分層設計,從上到下一次爲: Embedder(嵌入器)、Engine、Framework

Embedder是嵌入層,做好這一層的適配 Flutter 基本可以嵌入到任何平臺上去;
Engine層主要包含 Skia、Dart 和 Text。Skia 是開源的二位圖形庫;Dart 部分主要包括 runtime、Garbage Collection、編譯模式支持等;Text 是文本渲染。
Framework在最上層。我們的應用圍繞 Framework 層來構建,因此也是本文要介紹的重點。

5.【Rendering】是框架中的渲染庫。控件的渲染主要包括三個階段:佈局(Layout)、繪製(Paint)、合成(Composite)。


圖2: Flutter 流水線
首先是獲取到用戶的操作,然後你的應用會因此顯示一些動畫,接着 Flutter 開始構建 Widget 對象。
Widget 對象構建完成後進入渲染階段,這個階段主要包括三步:
* 佈局元素:決定頁面元素在屏幕上的位置和大小;
* 繪製階段:將頁面元素繪製成它們應有的樣式;
* 合成階段:按照繪製規則將之前兩個步驟的產物組合在一起。
最後的光柵化由 Engine 層來完成。


在渲染階段,控件樹(widget)會轉換成對應的渲染對象(RenderObject)樹,在 Rendering 層進行佈局和繪製。

在佈局時 Flutter 深度優先遍歷渲染對象樹。數據流的傳遞方式是從上到下傳遞約束,從下到上傳遞大小。也就是說,父節點會將自己的約束傳遞給子節點,子節點根據接收到的約束來計算自己的大小,然後將自己的尺寸返回給父節點。整個過程中,位置信息由父節點來控制,子節點並不關心自己所在的位置,而父節點也不關心子節點具體長什麼樣子。


【Widget】控件層。所有控件的基類都是 Widget,Widget 的數據都是隻讀的, 不能改變。所以每次需要更新頁面時都需要重新創建一個新的控件樹。每一個 Widget 會通過一個 RenderObjectElement 對應到一個渲染節點(RenderObject),可以簡單理解爲 Widget 中只存儲了頁面元素的信息,而真正負責佈局、渲染的是 RenderObject。
Widget -> RenderObjectElement 對應到一個渲染節點-> RenderObject
RenderObjectElement 樹會盡量保持重用。由於 RenderObjectElement 持有對應的 RenderObject,所有 RenderObject 樹也會盡可能的被重用。

如果想把方形的顏色換成黃色,將圓形的顏色變成紅色,由於控件是不能被修改的,需要重新生成兩個新的控件 Rectangle yellow 和 Circle red。由於只是修改了顏色屬性,所以 Element 和 RenderObject 都被重用,而之前的控件樹會被釋放回收。

widget 是view嗎
widget是對頁面UI的一種描述。widget在渲染的時候會轉化成element,Element相比widget相比於widget增加了上下文的信息。。element是對應widget,在渲染樹的實例化節點。由於widget是immutable的,所以同一個widget可以同時描述多個渲染樹中的節點。
所以同一個widget可以同時描述多個渲染樹中的節點。但是Element是描述固定在渲染書中的某一個特定位置的點。

簡單點說widget作爲一種描述是可以複用的,但是element卻跟需要繪製的節點一一對應。element繪製時會轉化成rendObject。RendObject纔是真正經過layout的paint並繪製在屏幕上的對象,在flutter中有三套渲染相關的tree,分別是widget tree & relement tree &rendObject tree。

flutter是響應式的框架。在某一時刻頁面的佈局,可能受不同的輸入源的影響。
Element這層實際上做了對某一時刻事件的彙總,在將真正需要修改的部分同步到真實的
rendObject tree上。

7. 最後是【Material】 & 【Cupertino】,這是在 Widget 層之上框架爲開發者提供的基於兩套設計語言實現的 UI 控件,可以幫助我們的 App 在不同平臺上提供接近原生的用戶體驗。

///// 爲什麼widget都是immutable
flutter界面開發是一種響應式編程,主張sImple is fast, flutter設計的初衷希望數據變更時發送通知到對應的可變更節點。由上到下重新create widget樹進行刷新。

如何觸發樹更新
1. 全局更新:調用runApp(rootWidget),一般flutter啓動時調用後不再會調用
2. 局部子樹更新, 將該子樹做StatefullWidget的一個子widget,並創建對應的State類實例,通過調用state.setState() 觸發該子樹的刷新

 

StatefullWidget vs StatelessWidget
1. StatelessWidget:無中間狀態變化的widget,需要更新展示內容就得通過重新new,flutter推薦儘量使用StatelessWidget
2. StatefullWidget:存在中間狀態變化,那麼問題來了,widget不是都immutable的,狀態變化存儲在哪裏?flutter 引入state的類用於存放中間態,通過調用state.setState()進行此節點及以下的整個子樹更新。單純改變數據是不會引發UI改變的

 

 

 

 

 

 

 

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章