本文對Flutter的29種佈局控件進行了總結分類,講解一些佈局上的優化策略,以及面對具體的佈局時,如何去選擇控件。git
前先後後也算是拖拖拉拉的寫了一些Flutter的文章,寫的也都比較粗略。最近工做調動,內部換了部門,一頓瞎忙活,也打亂了本來的分享計劃。程序員
從我最開始接觸Flutter到如今,差很少四個多月了。在這段時間裏面,Flutter也發佈了Release Preview版本。各個技術網站本着先撥頭籌的心態,推廣了幾波,國內的人氣跟着也起來了很多。全世界Flutter開發人員中,國內從業者佔據了很大的比重,這個現象自己並不能說明什麼,不過能夠反映一點,有商業訴求吧。固然觀望的仍是佔絕大部分,除了一些我的開發者愛折騰外,也就是一些大的業務成熟到不能再成熟的團隊,內部消化人員去折騰這個了。github
插個題外話,有感於最近的工做變更,這段時間胡思亂想的比較多。一門技術對程序員來講到底意味着什麼?若是不須要再爲生計奔波,是否還會對目前已上手的技術感興趣?若是你如今的項目所須要的技術,對你我的而言毫無加成,只會浪費你的時間,讓你在已有的技術棧上漸行漸遠,你是否還會參與這個項目。只有極少數人會趕上逆天改命的項目,無論參與什麼項目,技術人員的立身之本始終是技術(高管或者打算換行的除外),技術的選型,除去時間效率後續維護等普適性的考慮要素外,排在第一位的始終應該是對自身的提升,扯的有些遠了哈。web
我數了一下我文章總結過的佈局控件,總共有29種。乍看會以爲真雞毛的多,不乍看,也會以爲雞毛的真多。爲何其餘的移動平臺沒有這麼多佈局控件呢?其實否則,其餘平臺沒有這麼細分。性能優化
以Android平臺爲例,最基礎的幾種佈局例如LinearLayout、RelativeLayout、ConstraintLayout等等。不少Flutter的控件,對於Android來講,僅僅是一個屬性的設置問題。app
再往上看,iOS、Android、Web這些平臺的佈局,其實最基本就那幾種,線性佈局、絕對佈局、相對佈局等等。Flutter也逃不出這些,那爲何Flutter如今有這麼多佈局控件呢?less
第一點,以前文章介紹過的,Flutter的理念是萬物皆爲widget
。這和Flutter的實現機制有關,而不是由於它在佈局上有什麼特殊性,這也是最主要的一點。函數
第二點,我以爲是由於這是Flutter的初期,若是有經歷過一個技術的完整發展週期,就會明白,前期只是提供各類零件,只有商業支撐或者人員支撐足夠的時候,纔會去優化零件。而如今就是這麼一種資源不足的狀態。各類組件能夠合併的有不少,底層的實現機制不會變,只是再加一層便可,這也是能夠造輪子的地方,例如封裝一套適用於Android、iOS或者Web人員的控件庫等。工具
第三點,跟初期相關,一套新的技術,各類東西不可能一會兒全想明白,路老是走着走着才發現走歪了,就像一些控件,可能一些地方合適,可是一些新的地方又不太合適,因此就再造一個,因此有些控件看起來功能十分類似。佈局
說了這麼多,我其實就想說明一點,Flutter如今還只是處在社會發展的初級階段,還處在溫飽問題都解決不了的狀態,想達到小康還須要很長的一段路要走。
單節點控件,顧名思義就是隻有一個節點的佈局控件。這種控件有多少個呢,我以前文章總結過的有18種,現階段仍是不排除增長的可能,哈哈。
在這小節裏,我嘗試從多個維度去對這些控件進行分類,但願這樣能夠幫助你們理解。
上面是這18種控件的父節點層面的繼承關係,惟一不一樣的一個控件就是Container。因此按照是否繼承自SingleChildRenderObjectWidget的分類以下:
Container是一個組合控件,不是一個基礎控件,這點從繼承關係就能夠看出來。
分類以下:
先在此處小結一下,能夠看出Container的特殊之處了吧,爲何Container這麼特殊了。這個特殊要從兩個層面去看。
那能得出什麼結論呢?我我的以爲,Container這種組合的控件會愈來愈多,也會有我的開發者去開發這種通用型的組合控件,這是一個大趨勢,是Flutter走向易用的一小步。
在此處我按照定位、尺寸、繪製三部分來嘗試着去作功能的劃分,固然這個劃分並不絕對,仁者見仁吧。
有一個控件並無歸到這三類中,CustomSingleChildLayout能夠自定義實現,此處不作分類。Baseline能夠把它放到繪製裏面去,此處我按照調節文字的位置去作分類,這個你們知道就行,並非說只能這麼劃分。
對於繪製控件,其實分的有些雜,我把顯示相關的都歸到這裏,例如是否顯示、內邊距、是否超出顯示以及變形等等。
每一種大類,Flutter都提供了多種控件。通過這麼劃分,能夠看出不少控件功能的交叉,不少時候一個屬性的事情,Flutter仍是分出了一個控件。
單節點控件雖然這麼多,可是大部分不會挨個去嘗試。對於大部分人而言,都是佛系的用法,一個控件可以使用,就一直用到死。
在佈局上,大方向仍是不停的拆
,把一張設計圖,拆成一棵樹,每一個節點根據須要,選擇合適的控件,而後從根部開始不停嵌套,佈局就完成了。
控件種類繁多,真正使用的時候該如何去選擇呢?有萬金油的作法,無論啥都用Container,這也是不少初接觸的人常常乾的方式。這麼作的確能夠按照設計圖把佈局給實現了,可是會涉及到一些性能上的問題。
控件的選擇,按照控件最小功能的標準去選擇
。例如須要將子節點居中,可使用Container設置alignment的方式,也可使用Center。可是從功能上,Center是最小級別的,所以選擇它的話,額外的開銷會最小。
將UI實現了,這只是最基本的,當達到這一步了,應該更多的去思考,如何更好的佈局,使得性能更高。
多節點控件的種類就少了一些,雖然也有11種,可是功能和場景多了,因此選擇上反而會簡單一些。
多節點控件內部實現比單節點控件複雜的多,會從繼承以及功能兩個方向去作分類。
從上圖能夠看出,多節點佈局控件基本上能夠分爲三條線
以前介紹過,GridView和ListView的實現都是很是類似的,基本上就是silvers只包含一個Sliver(GridView爲SilverGrid、ListVIew爲SliverList)的CustomScrollView。 這也是爲啥這兩元素都繼承自BoxScrollView的緣故。
MultiChildRenderObjectWidget類,官方解讀以下
A superclass for RenderObjectWidgets that configure RenderObject subclasses that have a single list of children.
它只是一個含有單一list子節點的控件,爲何Table不須要繼承自MultiChildRenderObjectWidget呢?
這是由於Table的子節點是二維(橫豎)的,而MultiChildRenderObjectWidget提供的是一個一維的子節點管理,因此必須繼承自RenderObjectWidget。知道了這些事後,對繼承關係的理解會有更好的幫助。
這個對於多節點佈局控件來講,仍是比較難以劃分的,筆者試着作了以下劃分:
我的以爲這種分類方式不是特別的穩妥,但仍是寫下來了,請你們仁者見仁。
GridView和ListView分爲一類,一個是由於其實現很是的類似,另外一個緣由是這兩個控件內容區域能夠無限,不像其餘控件的內容區域都是固定的,所以將這兩個劃分爲一類。
關於單列單行多列多行的,也並非說很嚴格的,Row、Column、Table、ListBody可能會遵照這種劃分,Flow以及Wrap則是近似的多列多行。這種劃分絕對不是絕對的,只是我的的一種考量劃分方式。
多節點控件種類較少,並且功能重疊的不多,所以在使用上來講,仍是簡單一些。比較經常使用的GridView、ListView、Row、Column、Stack,這幾個控件基本上涵蓋了大部分的佈局了。
多節點控件功能重疊的較少,所以選擇上,不會存在太多模凌兩可的問題,須要什麼使用什麼便可。
性能優化這塊兒,可能仁者見仁,並無一個統一的說法,畢竟如今Flutter各方面都還不完善。可是,大方向仍是有的,儘可能使用功能集更小的控件,這個對於渲染效率上仍是有所幫助的。
在這裏我試着去列舉一些,並不必定都正確。
上面所列的比較雜,可是概括起來,無非這幾點:
控件的選擇,我的以爲把握大方向就夠了。若是時間緊急,以實現效率最優先,若是時間充裕的話,能夠按照一些優化細則,去作一些選擇。單純控件層面,帶來性能上的改進畢竟十分有限。
首先看一下實際的效果圖,這個是以前作工程中,比較複雜的一個界面吧,就算放到native上看,也是比較複雜的。
這個頁面中有很多自定義控件,例如日期選擇、進度等。總體看着複雜,實現起來其實也還好。關於如何佈局拆解,以前文章有過介紹,在這裏再也不闡述,訣竅就是一個字----拆。
自定義控件通常都是繼承自StatelessWidget、StatefulWidget。也有一些特殊的,例如上面的進度控件,直接使用Canvas畫的。
對於須要更新狀態的,通常都是繼承自StatefulWidget,對於不須要更新狀態的,使用StatelessWidget便可,可以使用StatelessWidget的時候,也儘可能使用它,StatefulWidget在頁面更新的時候,會存在額外的開銷。
Flutter的自定義控件,寫起來可能會比原生的更簡單,它更多的是一些基礎控件的組合使用,而不多涉及到底層的一些重寫。
這是很蛋疼的一個問題,一個純Flutter的App,相似於Android中的單Activity應用。某個具體的頁面就算去監聽native層的生命週期,也僅僅是獲取到base activity的,而沒法獲取到頁面層級的。
Flutter若是輪子足夠的話,仍是很是吸引人的,在熟悉了這些基礎組件事後,編寫起來,速度會很是快。自定義控件的實現,也比較簡單。可是,性能方面,仍是存在比較大的問題,複雜頁面首次載入,速度仍是比較慢。對於高端機型來講,總體流暢度很不錯,堪比原生的app,低端機型,表現就比較捉急吧。總體來講,Flutter表現仍是挺不錯的,能夠上手試試,把玩把玩吧。就是寫起來,寫着寫着就以爲噁心,是真的噁心的那種噁心,看着各類嵌套標籤,感受被降維成了web開發。
近期看到一些基於Flutter的自動佈局解決方案,以前也有想過,徹底能夠基於Flutter作出佈局的工具,僅僅是拖拽就能夠實現完成度很是高的佈局頁面。也得益於Flutter自己的思想和實現機制,web方面的不少東西,我的以爲均可以借鑑到Flutter上。單純從UI層來講,Flutter確實有本身獨特的地方。若是Flutter在最開始,就僅僅是一套跨平臺的UI的話,可能更容易被人們接受吧。
前幾天看了官方的camera插件,仍是挺蛋疼的,對於國內的Android端來講,直接拿來商用幾乎是不可能的。插件基於camera2去實現,國內大部分廠商對於camera2的支持不好,一些很容易復現的crash也沒有去解決。
若是決定在現有項目中使用Flutter,則須要作好埋坑造輪子的覺悟。若是人力緊缺的話,不該該在這上面去投入,人力富餘的時候,能夠投入人力跟進研究,讓業界以爲大家很棒很前沿。
筆者建了一個Flutter學習相關的項目,Github地址,裏面包含了筆者寫的關於Flutter學習相關的一些文章,會按期更新,也會上傳一些學習Demo,歡迎你們關注。