Widget是開發Flutter應用過程當中,接觸最多的概念。Flutter的理念是萬物皆Widget(Everything is Widget),這是爲了實現Flutter的一個設計理念:激進式組合(Aggressive composability)。Widget由一系列的小的Widget組合而成,而這些進行組合的Widget,自己是由更基礎的Widget構成。例如,Padding也是一種Widget,而不是Widget中的一個屬性。html
在Flutter中,Widget的定義是:描述一個UI元素的配置數據。它並非表示最終繪製在設備上的顯示元素,而只是描述顯示元素的一個配置數據。其主要功能包括:web
如上圖所示,Widget從功能上看,能夠分爲三大類:數組
組合類Widget。這類Widget主要用來組合其餘更基礎的Widget,獲得功能更加複雜的Widget。日常的業務開發通常用的就是此類Widget。markdown
渲染類Widget,這類Widget是框架最核心的Widget,會參與後面的佈局和渲染流程;只有這種類型的Widget會繪製到屏幕上。架構
代理類Widget,其自己並不涉及Widget內部邏輯,只是爲子Widget提供一些附加的中間功能。例如:InheritedWidget用於將一些狀態信息傳遞給子孫Widget。app
前面說過,Widget的功能是描述一個UI元素的配置數據,真正表明屏幕上顯示元素的類是Element。並且,一個Widget能夠對應多個Element,緣由是同一個Widget對象能夠被添加到UI樹的不一樣部分。關於Element的介紹,以及Widget和Element的關係咱們將在後面深刻介紹。如今須要記住如下兩點:框架
如下是一個Widget對象對應多個Element對象的一個示例:less
class SameWidgetMultiElementWidget1 extends StatefulWidget {
@override
_SameWidgetMultiElementWidgetState createState() => new _SameWidgetMultiElementWidgetState();
}
class _SameWidgetMultiElementWidgetState extends State<SameWidgetMultiElementWidget1> {
int count = 0;
@override
Widget build(BuildContext context) {
Text testText = Text("multi element");
return Column(
children: <Widget>[
testText,
testText,
],
);
}
}
複製代碼
其對應的Widget Tree和Element Tree以下:ide
在上面示例中,左邊是Widget Tree,右邊是Element Tree。在Widget Tree中,Column有兩個子節點,可是這兩個子節點使用的是同一個Text對象,所以這個Text對象出如今兩個不一樣的位置(Slot),此時在Element Tree會生成兩個不一樣的StatelessElement對象,即一個Text對象對應兩個StatelessElement對象。svg
StatelessWidget是咱們常常接觸的一類widget,其適用於不須要維護組件狀態的場景。其核心函數以下:
源碼以下:
@override
StatelessElement createElement() => StatelessElement(this);
複製代碼
該函數用於建立StatelessElement,通常用戶不用重寫該函數。
源碼以下:
@protected
Widget build(BuildContext context);
複製代碼
該函數是Widget的核心方法之一,主要用於向用戶提供描繪用戶界面的接口。用戶經過此函數組合用戶須要的子Widget,Framework則經過調用該方法,將用戶定義的Widget組合加入到Widget Tree中。其調用場景主要有兩種:
StatefulWidget適用於須要維護組件狀態的場景,它自己是不可變的,可是它有一個可變的State。所以,它持有的State一般被用於記錄狀態數據,例如計數器中的計數等。其核心函數以下:
源碼以下:
@override
StatefulElement createElement() => StatefulElement(this);
複製代碼
該函數用於建立StatefulElement ,通常用戶不用重寫該函數。
源碼以下:
@protected
@factory
State createState();
複製代碼
該函數用於建立對應的State,用戶經過該方法建立其須要保存數據的State。Framework在一個StatefulWidget的生命週期內,可能會屢次調用該函數。例如,假如一個StatefulWidget被加入Widget Tree多個位置,Framework將爲每一個位置建立一個單獨的State.
State表示對應的StatefulElement須要保存的信息,其有如下特色:
State生命週期各主要函數以下:
當Widget第一次插入到Widget Tree時會被調用,對於每個State對象,Flutter Framework只會調用一次該回調,因此,一般在該回調中作一些一次性的操做,如狀態初始化、訂閱子樹的事件通知等。
當State對象的依賴發生變化時會被調用;其主要場景有兩個:
此回調讀者如今應該已經至關熟悉了,它主要是用於構建Widget子樹的,會在以下場景被調用:
此回調是專門爲了開發調試而提供的,在熱重載(hot reload)時會被調用,此回調在Release模式下永遠不會被調用。
在Widget從新構建時,Flutter Framework會調用Widget.canUpdate來檢測Widget Tree中同一位置的新舊節點,而後決定是否須要更新,若是Widget.canUpdate返回true則會調用此回調。
當State對象從樹中被移除時,會調用此回調。在一些場景下,Flutter Framework會將State對象從新插到樹中,如包含此State對象的子樹在樹的一個位置移動到另外一個位置時(能夠經過GlobalKey來實現)。若是移除後沒有從新插入到樹中則緊接着會調用dispose方法。
當State對象從樹中被永久移除時調用;一般在此回調中釋放資源。
State生命週期以下:
RenderObjectWidget爲RenderObjectElement提供了配置,是真正負責渲染的Widget。其核心函數以下:
該函數用於建立對應的RenderObject。
該函數用於根據此Widget的配置更新對應的RenderObject。注意此函數不該該更新RenderObject的子節點。
該函數用於在RenderObject被從樹中移除的時候,清理RenderObject的資源。
本文主要介紹了Widget的類型及核心函數,其重點以下:
1. 深刻淺出 Flutter Framework 之 Widget
2. Flutter實戰
Flutter框架分析(一)--架構總覽
Flutter框架分析(三)-- Element
Flutter框架分析(四)-RenderObject
Flutter框架分析(五)-Widget,Element,RenderObject樹
Flutter框架分析(六)-Constraint
Flutter框架分析(七)-relayoutBoundary
Flutter框架分析(八)-Platform Channel
Flutter框架分析- Parent Data
Flutter框架分析 -InheritedWidget