一导坟、Flutter 簡介
Flutter是 Google 于 2015 年 5 月 3 日推出的免費(fèi)開源跨平臺開發(fā)框架闷游,可以快速在iOS和Android上構(gòu)建高質(zhì)量的原生用戶界面顶伞。Flutter幫助開發(fā)者使用一套代碼開發(fā)高性能憾儒、高穩(wěn)定性碰声、高幀率耍共、低延遲的Android和iOS應(yīng)用烫饼。Flutter使用的是 Google 自己開發(fā)的網(wǎng)絡(luò)編程語言——Dart 語言。Dart 語言是由Google公司開發(fā)的網(wǎng)絡(luò)編程語言试读,是面向?qū)ο蟮母茏荩惗x的,單繼承語言
二钩骇、Flutter 框架特性
快速開發(fā)
Flutter的熱重載能力幫助開發(fā)者快捷方便的試驗(yàn)比藻、重構(gòu)UI、添加特性和修復(fù)bug倘屹。在仿真器银亲、模擬器、ios纽匙、android硬件上體驗(yàn)亞秒級的重載务蝠,而不會丟失狀態(tài)。
跨平臺
Flutter 基于圖像繪制引擎進(jìn)行渲染烛缔,在不同平臺下繪制效果絕對一致馏段,能做到真正的跨平臺。
絢麗UI
通過Flutter內(nèi)建的践瓷、漂亮的院喜、有質(zhì)感設(shè)計(jì)的Cupertino(ios-flavor)小工具、豐富的動畫API当窗,平滑的自然滾動和平臺感知够坐,讓用戶感受UI設(shè)計(jì)的快樂。
響應(yīng)式框架
通過Flutter的現(xiàn)代響應(yīng)式(Reactive)框架、豐富的平臺布局元咙、基礎(chǔ)組件梯影,能夠輕松的構(gòu)建用戶界面。使用強(qiáng)大而靈活的API解決2D庶香、動畫甲棍、手勢、效果等難題赶掖。
支持插件感猛,訪問原生功能
通過平臺api、第三方sdk和原生代碼奢赂,使應(yīng)用變得生動陪白。Flutter可以重用現(xiàn)有的java、swift和Objc代碼膳灶,并在iOS和Android上訪問原生特性和SDK咱士。
三、目前各種跨平臺方案的對比
開發(fā)APP應(yīng)用轧钓,如需要同時兼容 iOS 和 Android 兩種平臺序厉,有兩種技術(shù)選擇:
1、走原生開發(fā)路線毕箍,把界面和邏輯在不同平臺分別實(shí)現(xiàn)弛房;
2、用同一套代碼兼容多個平臺而柑,但這往往意味著運(yùn)行速度和產(chǎn)品體驗(yàn)的損失文捶。
除了原生外,目前跨平臺技術(shù)一般是混合開發(fā)牺堰,如采用 H5拄轻、React Native、Weex伟葫、小程序等技術(shù)實(shí)現(xiàn)跨平臺應(yīng)用恨搓。不過這些混合開發(fā),或多或少都能感覺到UI卡頓和體驗(yàn)不流暢筏养,并且開發(fā)和學(xué)習(xí)成本非常高斧抱,有各自的局限性。
Flutter 的出現(xiàn)渐溶,為開發(fā)者提供了一套兩全其美的解決方案:既能用原生代碼直接調(diào)用的方式來加速圖形渲染和 UI 繪制辉浦,又能同時運(yùn)行在兩大主流移動操作系統(tǒng)上,并且體驗(yàn)和流暢度和原生基本一致茎辐、開發(fā)效率非常高宪郊、學(xué)習(xí)難度和成本低掂恕。
從上面的對比可以看出,F(xiàn)lutter 優(yōu)勢明顯:高體驗(yàn)度弛槐、高開發(fā)效率懊亡、低學(xué)習(xí)成本、高可擴(kuò)展性乎串。未來 Google Flutter 團(tuán)隊(duì)還將會使 Flutter 支持 PC 和 Web 的跨平臺開發(fā)店枣,實(shí)現(xiàn)真正全平臺。 針對Flutter的跨平臺特性叹誉,與react native鸯两、weex做對比可以發(fā)現(xiàn),其性能碾壓后兩者长豁,采用自帶Skia繪制引擎钧唐,性能堪比原生。
四蕉斜、 介紹下Flutter的架構(gòu)理念
由上圖可知逾柿,F(xiàn)lutter框架自下而上分為Embedder、Engine和Framework三層宅此。其中,Embedder是操作系統(tǒng)適配層爬范,實(shí)現(xiàn)了渲染 Surface設(shè)置父腕,線程設(shè)置,以及平臺插件等平臺相關(guān)特性的適配青瀑;Engine層負(fù)責(zé)圖形繪制璧亮、文字排版和提供Dart運(yùn)行時,Engine層具有獨(dú)立虛擬機(jī)斥难,正是由于它的存在枝嘶,F(xiàn)lutter程序才能運(yùn)行在不同的平臺上,實(shí)現(xiàn)跨平臺運(yùn)行哑诊;Framework層則是使用Dart編寫的一套基礎(chǔ)視圖庫群扶,包含了動畫、圖形繪制和手勢識別等功能镀裤,是使用頻率最高的一層竞阐。
介紹下Flutter的FrameWork層和Engine層,以及它們的作用
Flutter的FrameWork層是用Drat編寫的框架(SDK)暑劝,它實(shí)現(xiàn)了一套基礎(chǔ)庫骆莹,包含Material(Android風(fēng)格UI)和Cupertino(iOS風(fēng)格)的UI界面,下面是通用的Widgets(組件)担猛,之后是一些動畫幕垦、繪制丢氢、渲染、手勢庫等先改。這個純 Dart實(shí)現(xiàn)的 SDK被封裝為了一個叫作 dart:ui的 Dart庫疚察。我們在使用 Flutter寫 App的時候,直接導(dǎo)入這個庫即可使用組件等功能盏道。
Flutter的Engine層是Skia 2D的繪圖引擎庫稍浆,其前身是一個向量繪圖軟件,Chrome和 Android均采用 Skia作為繪圖引擎猜嘱。Skia提供了非常友好的 API衅枫,并且在圖形轉(zhuǎn)換、文字渲染朗伶、位圖渲染方面都提供了友好弦撩、高效的表現(xiàn)。Skia是跨平臺的论皆,所以可以被嵌入到 Flutter的 iOS SDK中益楼,而不用去研究 iOS閉源的 Core Graphics / Core Animation。Android自帶了 Skia点晴,所以 Flutter Android SDK要比 iOS SDK小很多感凤。
五、Flutter 性能優(yōu)化
1.重建最小化原則
在調(diào)用?setState()?方法重建組件時粒督,一定要最小化重建組件陪竿,沒有變化的組件不要重建
點(diǎn)擊按鈕調(diào)用setstate, 可以看到每次重建的widget, 需要變化的組件盡量抽取
不變組件建議加上const, 在調(diào)用setstate時,也是不會重建
2.避免更改組件樹的結(jié)構(gòu)和組件的類型
3.關(guān)于Listview優(yōu)化
ListView是我們最常用的組件之一,用于展示大量數(shù)據(jù)的列表屠橄。如果展示大量數(shù)據(jù)請使用?ListView.builder?或者?ListView.separated
4.關(guān)于 AnimatedBuilder TweenAnimationBuilder 的優(yōu)化
這里說的是向AnimatedBuilder 族跛、TweenAnimationBuilder 等一類的組件的問題,這些組件都有一個共同點(diǎn)锐墙,帶有 builder 且其參數(shù)重有 child礁哄。
以 AnimatedBuilder 為例,如果 builder 中構(gòu)建的樹中包含與動畫無關(guān)的組件溪北,將這些無關(guān)的組件當(dāng)作 child 傳遞到 builder 中比直接在 builder 中構(gòu)建更加有效桐绒。
5.謹(jǐn)慎的使用一些組件
六、Flutter是如何做到一套Dart代碼可以編譯運(yùn)行在Android和iOS平臺的刻盐?所以說具體的原理掏膏。
Skia繪制,實(shí)現(xiàn)跨平臺應(yīng)用層渲染一致性
Method Channel 機(jī)制
為了解決調(diào)用原生系統(tǒng)底層能力以及相關(guān)代碼庫復(fù)用問題敦锌,F(xiàn)lutter 為開發(fā)者提供了一個輕量級的解決方案馒疹,即邏輯層的方法通道(Method Channel)機(jī)制∫仪剑基于方法通道颖变,我們可以將原生代碼所擁有的能力生均,以接口形式暴露給 Dart,從而實(shí)現(xiàn) Dart 代碼與原生代碼的交互腥刹,就像調(diào)用了一個普通的 Dart API 一樣马胧。
Flutter定義了三種不同類型的Channel
BasicMessageChannel:用于傳遞字符串和半結(jié)構(gòu)化的信息。
MethodChannel:用于傳遞方法調(diào)用(method invocation)衔峰。
EventChannel: 用于數(shù)據(jù)流(event streams)的通信佩脊。
注意
Method Channel 是非線程安全的。原生代碼在處理方法調(diào)用請求時垫卤,如果涉及到異步或非主線程切換威彰,需要確保回調(diào)過程是在原生系統(tǒng)的 UI 線程(也就是 Android 和 iOS 的主線程)中執(zhí)行的穴肘,否則應(yīng)用可能會出現(xiàn)奇怪的 Bug歇盼,甚至是 Crash。
七评抚、Flutter 布局
Flutter中擁有30多種預(yù)定義的布局widget豹缀,常用的有Container、Padding慨代、Center邢笙、Flex、Row侍匙、Colum鸣剪、ListView、GridView丈积。按照《Flutter技術(shù)入門與實(shí)戰(zhàn)》上面來說的話,大概分為四類
基礎(chǔ)布局組件:Container(容器布局)债鸡,Center(居中布局)江滨,Padding(填充布局),Align(對齊布局)厌均,Colum(垂直布局)唬滑,Row(水平布局),Expanded(配合Colum棺弊,Row使用)晶密,FittedBox(縮放布局),Stack(堆疊布局)模她,overflowBox(溢出父視圖容器)稻艰。
寬高尺寸處理:SizedBox(設(shè)置具體尺寸),ConstrainedBox(限定最大最小寬高布局)侈净,LimitedBox(限定最大寬高布局)尊勿,AspectRatio(調(diào)整寬高比)僧凤,FractionallySizedBox(百分比布局)
列表和表格處理:ListView(列表),GridView(網(wǎng)格)元扔,Table(表格)
其它布局處理:Transform(矩陣轉(zhuǎn)換)躯保,Baseline(基準(zhǔn)線布局),Offstage(控制是否顯示組件)澎语,Wrap(按寬高自動換行布局)
八途事、Flutter 動畫類型
1.基于圖形動畫(以圖形的形式制作動畫,三方庫 Rive 擅羞、Lottie)尸变、
2.基于代碼動畫 (主要針對于 Widgets 的大小、 顏色祟滴、形狀變動)
在 Flutter 中基于代碼動畫振惰,也主要分為兩種形式:補(bǔ)間(Tween)動畫、 擬物動畫垄懂。
補(bǔ)間(Tween)動畫
Tween意為在兩者之間骑晶,在Tween動畫中我們定義開始點(diǎn)和結(jié)束點(diǎn)、時間線以及定義轉(zhuǎn)換時間和速度的曲線草慧。然后就交由框架完成如何從開始點(diǎn)過渡到結(jié)束點(diǎn)的動畫效果桶蛔。
物理動畫
物理動畫是對真實(shí)世界的行為進(jìn)行建模,使動畫效果類似于現(xiàn)實(shí)中的物理效果漫谷。例如當(dāng)你擲球時仔雷,它在何處落地,取決于拋球速度有多快舔示、球有多重碟婆、距離地面有多遠(yuǎn)。
Flutter 基礎(chǔ)動畫和相關(guān)類
Animation:Flutter中動畫的核心類
AnimationController:動畫的管理類
CurvedAnimation:用于定義非線性曲線動畫
Tween:補(bǔ)間對象惕稻,用于計(jì)算動畫使用的數(shù)據(jù)范圍之間的插值
Listeners 和StatusListeners:用于監(jiān)聽動畫狀態(tài)的改變
如何創(chuàng)建恰當(dāng)?shù)膭赢嫞?/b>
在知道Flutter的動畫類型之后竖共,我們需要知道如何創(chuàng)建我們想要的動畫效果,在 Flutter 動畫也被分為隱式動畫俺祠、 顯示動畫公给。當(dāng)我們創(chuàng)建一個動畫效果時,如果你不知道如何選擇這兩種方式蜘渣,你可以試著回答下面的三個問題:
1.動畫效果是否"永遠(yuǎn)"重復(fù)淌铐?永遠(yuǎn)是指某個條件下動畫一直重復(fù),當(dāng)條件變動時蔫缸,動畫可以停止腿准。
2.動畫的值是否不連續(xù)?如下圖圓從小到大捂龄、從小到大释涛,并未連續(xù)的小->大->小->大加叁。
3.動畫是否由多個Widgets共同組成?
如果以上三個問題唇撬,都是肯定的回答它匕,那么你需要的是顯示動畫,否則使用隱式動畫將會是你更好的選擇窖认。
隱式動畫
如果你選擇了隱式動畫之后豫柬,首先你可以嘗試在 Flutter 框架中尋找符合你要求的 Widgets,F(xiàn)lutter 對隱式動畫的命名方式一般為AnimatedFoo扑浸, 其中Foo是需要設(shè)置動畫的屬性烧给。如果找不到符合自己需求的內(nèi)置動畫Widget,我們可以使用TweenAnimationBuilder(補(bǔ)間動畫生成器)創(chuàng)建自定義的隱式動畫喝噪。
顯示動畫
如果你的選擇是顯示動畫础嫡,那么你也可以嘗試在 Flutter 框架中尋找符合Widgets。Flutter 對顯示動畫的命名方式一般為FooTransition酝惧, 其中Foo是需要設(shè)置動畫的屬性(如SlideTransition)榴鼎。如果找不到符合自己需求的內(nèi)置動畫Widget。你還有兩種選擇晚唇,創(chuàng)建獨(dú)立的動畫Widget(擴(kuò)展AnimatedWidget)巫财,或者擴(kuò)展Widget(使用AnimatedBuilder)。
如果在動畫執(zhí)行的過程中哩陕,碰到了性能的問題的話平项,我們可以考慮使用CustomPainter進(jìn)行動畫處理.
九、Flutter 中的狀態(tài)State
State是一個組件的UI數(shù)據(jù)模型悍及,是組件渲染時的數(shù)據(jù)依賴闽瓢,State狀態(tài)的生命周期
StatefulWidget.creatWidget:FrameWork會通過調(diào)用StatefulWidget.creatWidget來創(chuàng)建第一個State
initState:初始化調(diào)用
didChangeDependencies:initState調(diào)用結(jié)束后調(diào)用
build:通過Build 來構(gòu)建視圖,返回一個Widget
deactivate:State被暫時從試圖樹中移除時心赶,會調(diào)用這個函數(shù)鸳粉,暫停狀態(tài)
dispose:State被永久從試圖樹中移除時,調(diào)用這個方法园担,銷毀狀態(tài)
didUpdateWidget:當(dāng)Widget配置發(fā)生變化時會調(diào)用這個方法,比如熱重載枯夜,會重新build
setState:當(dāng)需要更新State試圖的時候弯汰,重新Build