如何安裝 Flutter 請(qǐng)點(diǎn)擊這里
1、Flutter 是什么?
Flutter是一款移動(dòng)應(yīng)用程序SDK唤冈,包含框架、widget和工具银伟,為開發(fā)人員提供了一種在Android和iOS上構(gòu)建和部署精美移動(dòng)應(yīng)用程序的簡(jiǎn)單高效的方式你虹。
2、Flutter 優(yōu)點(diǎn)與缺點(diǎn)
優(yōu)點(diǎn)
1彤避、性能強(qiáng)大傅物、流暢
- Flutter 對(duì)比 weex 和 react native ,性能強(qiáng)大是有目共睹的琉预,因?yàn)榛?dom 樹渲染原生組件董饰,很難與原生視圖繪圖比性能, Google 直接在兩個(gè)平臺(tái)上重寫了各自的 UIKit圆米, 直接對(duì)接平臺(tái)底層卒暂,減少 UI 層的多層轉(zhuǎn)換,讓 UI 的性能幾乎可以比肩原生娄帖,在列表的滑動(dòng)體驗(yàn)最為明顯也祠。
2、熱重載
簡(jiǎn)單的來說就是 比如我們改變了一些代碼(例如文本變了)近速,點(diǎn)擊 “熱重載” 或者 保存文件诈嘿,能在很短的時(shí)間內(nèi)看到結(jié)果堪旧,這樣體驗(yàn)是不是更好?
3永淌、UI穩(wěn)定
因?yàn)?Google 重寫了 UIKit崎场,不依賴 Css 解釋器,不會(huì)存在 UI 渲染不正常的情況遂蛀,讓 UI 的效果表現(xiàn)的更加穩(wěn)定。
4干厚、萬(wàn)物皆 Widget
Flutter 的核心原則 —— 所有東西都是一個(gè)小部件李滴。你的 app 類是一個(gè)小部件(MaterialApp),你的整體布局結(jié)構(gòu)也是一個(gè)小部件(Scaffold)蛮瞄,所有東西都是一個(gè)小部件(AppBar, Drawer, SnackBar)所坯。
有了 Fluter,創(chuàng)建 UI 就像用許多不同的小部件組合布局一樣簡(jiǎn)單挂捅。
Flutter 還有另外一個(gè)核心原則芹助,組合優(yōu)先于繼承。這意味著闲先,如果你想要?jiǎng)?chuàng)建一些新的部件(widget)状土,則可以使用幾個(gè) Widget 組成新的 Widget ,而不是擴(kuò)展現(xiàn)有的 Widget 類伺糠。
缺點(diǎn)
1蒙谓、假裝跨平臺(tái),躲不開原生代碼
這是最大的問題训桶,跨平臺(tái)框架說白了就是UI跨平臺(tái)累驮,最后還是在原生平臺(tái)運(yùn)行,本來兩個(gè)平臺(tái)就有天壤之別舵揭,一套代碼就想吃掉iOS和Android在實(shí)際應(yīng)用之中其實(shí)根本就不現(xiàn)實(shí)谤专。Flutter具有與原生代碼互相調(diào)用的能力固然非常科學(xué)午绳,但是問題反而顯得更加明顯——我一個(gè)前端工程師上哪里去知道什么是UIViewController置侍,什么是Activity呢?我要是雙端都熟悉箱叁,學(xué)習(xí)Flutter就顯得很沒有必要墅垮。這是一個(gè)很矛盾的點(diǎn),特別是在團(tuán)隊(duì)里耕漱,只有幾個(gè)前端突然想學(xué)Flutter算色,是絕對(duì)做不來大項(xiàng)目的,如果有原生開發(fā)者螟够,那就沒必要搞Flutter了灾梦。
2峡钓、資源管理不方便
Flutter 支持不同分辨率的圖片,但是目錄設(shè)計(jì)不合理若河,圖片不能直接拖到 Flutter 用能岩,這點(diǎn)設(shè)計(jì)讓我們使用起來極其麻煩。
3萧福、Widget 的類型初建項(xiàng)目難以抉擇
Flutter的Widget分為StatefulWidget和StatelessWidget兩種拉鹃,一種是帶狀態(tài)的一種是不帶狀態(tài)的,剛開發(fā)的時(shí)候很難想明白用哪個(gè)鲫忍,因?yàn)镾tatelessWidget也能存值膏燕,其實(shí)區(qū)別就在于框架重構(gòu)UI的時(shí)候會(huì)使用State來重構(gòu),如果是StatelessWidget悟民,暫時(shí)存進(jìn)去的值就沒了坝辫。
4、需要梯子射亏,因?yàn)橛袎Α?/p>
因?yàn)橹袊?guó)國(guó)情近忙,想更好的開發(fā) Flutter 需要有梯子,否則難度系數(shù)有點(diǎn)高智润。
3及舍、為什么Flutter選擇使用Dart語(yǔ)言?
Flutter在四個(gè)主要維度進(jìn)行了評(píng)估做鹰,并考慮了框架作者击纬、開發(fā)人員和最終用戶的需求等因素。我們發(fā)現(xiàn)不同的語(yǔ)言在不同的層面符合一部分需求钾麸,但Dart在所有評(píng)估維度上得分都很高更振,并且符合我們的所有要求和標(biāo)準(zhǔn)。
Dart運(yùn)行時(shí)和編譯器支持Flutter的兩個(gè)關(guān)鍵特性的組合:基于JIT的快速開發(fā)周期:允許使用類型的語(yǔ)言進(jìn)行形狀更改和有狀態(tài)的熱重載饭尝;以及AOT編譯器肯腕,可生成高效的ARM代碼,可以快速啟動(dòng)并擁有可預(yù)測(cè)的生產(chǎn)部署性能钥平。
此外实撒,我們有機(jī)會(huì)與Dart社區(qū)密切合作,Dart社區(qū)正在積極投入資源改進(jìn)Dart在Flutter中的使用涉瘾。例如知态,當(dāng)我們采用Dart時(shí),該語(yǔ)言沒有提供生成原生二進(jìn)制文件的工具鏈(這對(duì)于實(shí)現(xiàn)可預(yù)測(cè)的高性能是很有幫助的)立叛,但是現(xiàn)在實(shí)現(xiàn)了负敏,因?yàn)镈art團(tuán)隊(duì)為Flutter構(gòu)建了它。同樣秘蛇,Dart VM之前已經(jīng)針對(duì)吞吐量進(jìn)行了優(yōu)化其做,但團(tuán)隊(duì)現(xiàn)在正在優(yōu)化VM的延遲時(shí)間顶考,這對(duì)于Flutter的工作負(fù)載更為重要。
Dart在以下主要標(biāo)準(zhǔn)上得到高分:
開發(fā)人員的效率妖泄。Flutter的主要價(jià)值主張之一是通過讓開發(fā)人員使用相同的代碼庫(kù)為iOS和Android創(chuàng)建應(yīng)用程序驹沿,從而節(jié)省了工程資源。使用高效的語(yǔ)言可以進(jìn)一步加速開發(fā)周期蹈胡,并使Flutter更具吸引力渊季。這對(duì)我們的framework團(tuán)隊(duì)和開發(fā)人員都非常重要。大部分Flutter功能都是用Dart實(shí)現(xiàn)审残,因此我們需要在10萬(wàn)行代碼時(shí)能保持高效的而不會(huì)犧牲framework和widget的可讀性梭域。
面向?qū)ο?/strong>。雖然我們可以使用非面向?qū)ο蟮恼Z(yǔ)言搅轿,但這意味著要重新解決幾個(gè)難題。另外富玷,絕大多數(shù)開發(fā)人員都具有面向?qū)ο箝_發(fā)的經(jīng)驗(yàn)璧坟,因此更容易學(xué)習(xí)如何使用Flutter進(jìn)行開發(fā)。
可預(yù)測(cè)赎懦,高性能雀鹃。借助Flutter,我們希望使開發(fā)人員能夠快速創(chuàng)建流暢的用戶體驗(yàn)励两。為了實(shí)現(xiàn)這一點(diǎn)黎茎,我們需要能夠在每個(gè)動(dòng)畫幀中運(yùn)行大量的代碼。這意味著我們需要一種既能提供高性能又能提供可預(yù)測(cè)性能的語(yǔ)言当悔,而不會(huì)出現(xiàn)會(huì)導(dǎo)致丟幀的周期性暫停傅瞻。
快速內(nèi)存分配。Flutter框架使用函數(shù)式流盲憎,它很大程度上依賴于底層的內(nèi)存分配器嗅骄,從而有效地處理小的、短期的內(nèi)存分配會(huì)非常重要饼疙,所以在缺乏此功能的語(yǔ)言中Flutter無(wú)法有效地工作溺森。
4、快速了解 Flutter 上手更容易
從上圖我們能夠看出 Flutter 的核心設(shè)計(jì)圍繞著 Widget 的窑眯。
1屏积、組件
Text
Text 是UI開發(fā)的最重要的組件之一,文字展示都要靠 Text 組件來完成磅甩,
Flutter的 Text組件 屬性很豐富炊林。const Text(this.data, { Key key, this.style, //風(fēng)格樣式,沒設(shè)置的話默認(rèn)使用 DefaultTextStyle this.textAlign, //文本水平如何對(duì)齊 this.textDirection, //方向性 this.locale, this.softWrap, // 文本是否換行符換行更胖,如何為false铛铁,那么文本就會(huì)一直水平顯示 this.overflow, // 處理文本溢出的視覺效果 this.textScaleFactor, //字體像素?cái)?shù) this.maxLines, //可選的文本最大行數(shù)隔显,必要時(shí)進(jìn)行換行。 this.semanticsLabel, //語(yǔ)義標(biāo)簽 }) : assert(data != null), textSpan = null, super(key: key);
Image
const Image({ Key key, @required this.image, this.semanticLabel, //圖像的語(yǔ)義描述 this.excludeFromSemantics = false, //是否從語(yǔ)義中刪除該圖像饵逐。 this.width, //寬度 this.height, //高度 this.color, // 顏色 this.colorBlendMode, // 讓顏色和圖混合在一起 this.fit, // 如何將圖像顯示括眠。有以下幾種模式 fill 、contain倍权、cover掷豺、fitWidth、fitHeight薄声、none当船、scaleDown this.alignment = Alignment.center, // 圖片的邊界內(nèi)對(duì)齊。 this.repeat = ImageRepeat.noRepeat, // 繪制沒有被圖片覆蓋的部分 this.centerSlice, //圖像中心切片內(nèi)的區(qū)域?qū)⑼瑫r(shí)被拉伸 this.matchTextDirection = false, //是否按照 TextDirection 的方向繪制圖了 this.gaplessPlayback = false, //是繼續(xù)顯示舊圖片默辨,還是不顯示 (圖片被修改時(shí)) this.filterQuality = FilterQuality.low, //設(shè)置質(zhì)量 }) : assert(image != null), assert(alignment != null), assert(repeat != null), assert(filterQuality != null), assert(matchTextDirection != null), super(key: key);
Container(容器)
Container 本身是一個(gè)widget德频。但是他卻提供了對(duì)基礎(chǔ)widget的封裝,提高了UI基礎(chǔ)裝飾能力的表達(dá)效率缩幸。
Container({ Key key, this.alignment, // 容器內(nèi)對(duì)齊 this.padding, //設(shè)置內(nèi)邊距屬性壹置,內(nèi)邊距的空白區(qū)域 示例 new EdgeInsets.all(8.0), Color color, //顏色 Decoration decoration, // 一般實(shí)際場(chǎng)景中會(huì)使用他的子類BoxDecoration。BoxDecoration提供了對(duì)背景色表谊,邊框钞护,圓角,陰影和漸變等功能的定制能力爆办。 this.foregroundDecoration, // decoration 要設(shè)置在 child 前面 double width, //寬 double height, // 高 BoxConstraints constraints, //約束 this.margin, // decoration 與 child 的空間 this.transform, // decoration 轉(zhuǎn)換 this.child, // 容器內(nèi)的元素 例如 Text('我是誰(shuí)'), })
GestureDetector(手勢(shì))
使用時(shí)只需要將GestureDetector包裹在目標(biāo)widget外面难咕,再實(shí)現(xiàn)對(duì)應(yīng)事件的函數(shù)即可。從點(diǎn)擊到長(zhǎng)按距辆,從縮放到拖動(dòng)余佃,這個(gè)類基本上都有相應(yīng)的實(shí)現(xiàn)。
GestureDetector({ Key key, this.child, this.onTapDown, this.onTapUp, this.onTap, this.onTapCancel, this.onDoubleTap, this.onLongPress, this.onLongPressUp, this.onVerticalDragDown, this.onVerticalDragStart, this.onVerticalDragUpdate, this.onVerticalDragEnd, this.onVerticalDragCancel, this.onHorizontalDragDown, this.onHorizontalDragStart, this.onHorizontalDragUpdate, this.onHorizontalDragEnd, this.onHorizontalDragCancel, this.onForcePressStart, this.onForcePressPeak, this.onForcePressUpdate, this.onForcePressEnd, this.onPanDown, this.onPanStart, this.onPanUpdate, this.onPanEnd, this.onPanCancel, this.onScaleStart, this.onScaleUpdate, this.onScaleEnd, this.behavior, this.excludeFromSemantics = false })
2挑格、布局
Flutter布局分為:
SingleChildRenderObjectWidget
1咙冗、 center
2、padding
3漂彤、containerMultiChildRenderObjectWidget
1雾消、stack
2、flex
3挫望、flow
Flex
Flex.png
上面的是 flex 布局概念
flex通過direction設(shè)置了flex的主軸方向即main axis立润。
和主軸垂直的方向叫做cross axis。
flex布局中對(duì)子布局的控制是從main axis 和cross axis兩個(gè)方向上進(jìn)行的媳板。
例如居中有main axis居中和cross axis居中桑腮。兩者都居中才是容器的完全居中。crossAxisAlignment蛉幸、mainAxisAlignment 和 Column 破讨、Row 一起使用更爽
Column.pngRow.png
Stack (實(shí)現(xiàn)層式布局)
開發(fā)過程中丛晦,我們通常需要在一些 Widgets 的上面再覆蓋上新的 Widgets 。
我們就用到了 Stack
- positioned 可以通過Positioned屬性靈活定位
- non-positioned 通過父Widget Stack 的屬性來控制布局
對(duì)于non-positioned children提陶, 我們通過控制Stack的alignment屬性來控制對(duì)齊方式烫沙。
Positioned的布局方式類似于H5&weex中的position布局中的absolute布局方式。
通過設(shè)置距離父組件上下左右的距離隙笆,Positioned對(duì)象能在Stack布局中更加靈活的控制view的展現(xiàn)方式锌蓄。
組件隱藏
- 父容器的list中 刪除要隱藏的cell
- offstage 屬性設(shè)置為 true ,在Offstage 上面的 child 包括它本身都不會(huì)被繪制撑柔。
- 使用透明度(不建議使用)
3瘸爽、生命周期
Stack 生命周期
didChangeDependencies state依賴的對(duì)象發(fā)生變化時(shí)調(diào)用
名稱 狀態(tài) initState 插入渲染樹時(shí)調(diào)用,只調(diào)用一次 didChangeDependencies state依賴的對(duì)象發(fā)生變化時(shí)調(diào)用 didUpdateWidget 組件狀態(tài)改變時(shí)候調(diào)用铅忿,可能會(huì)調(diào)用多次 build 構(gòu)建Widget時(shí)調(diào)用 deactivate 當(dāng)移除渲染樹的時(shí)候調(diào)用 dispose 組件即將銷毀時(shí)調(diào)用 state 生命周期.png注意
這里的狀態(tài)改變包括兩種可能:
1.通過setState內(nèi)容改變
2.父節(jié)點(diǎn)的state狀態(tài)改變剪决,導(dǎo)致子節(jié)點(diǎn)的同步變化。
StatelessWidget 和 StatefulWidget的區(qū)別
StatelessWidget是狀態(tài)不可變的widget檀训。初始狀態(tài)設(shè)置以后就不可再變化昼捍。如果需要變化需要重新創(chuàng)建。
StatefulWidget可以保存自己的狀態(tài)肢扯。
那問題是既然widget都是immutable的,怎么保存狀態(tài)担锤?
其實(shí)Flutter是通過引入了State來保存狀態(tài)蔚晨。當(dāng)State的狀態(tài)改變時(shí),能重新構(gòu)建本節(jié)點(diǎn)以及child的Widget樹來進(jìn)行UI變化肛循。
注意:如果需要主動(dòng)改變State的狀態(tài)铭腕,需要通過setState()方法進(jìn)行觸發(fā),單純改變數(shù)據(jù)是不會(huì)引發(fā)UI改變的多糠。
內(nèi)存問題
目前發(fā)現(xiàn)的問題:大量的push 加載 圖片會(huì)造成內(nèi)存暴漲導(dǎo)致閃退累舷,
原因:是 Flutter 的加載機(jī)制,如果不進(jìn)行任何處理夹孔, 每次加載圖片被盈,不管有沒有渲染到界面上的圖片都會(huì)去加載,所以頻繁刷頁(yè)面會(huì)造成內(nèi)存峰值過高搭伤,關(guān)于 widgets 官方介紹點(diǎn)擊這里
解決:在頁(yè)面不可見的時(shí)候不發(fā)出多余的圖片加載請(qǐng)求只怎。
內(nèi)存調(diào)試工具 Xcode Instruments
部分內(nèi)容借鑒引用咸魚技術(shù)