Stateful or Stateless widgets?git
在建立一個Flutter App的時候,會遇到兩種類型的控件github
在建立控件的時候,有一些控件不須要管理控件內部狀態,這個時候就能夠選擇無狀態控件。無狀態控件除了用數據初始化之外的時刻,不須要改變它的狀態。bash
在Flutter中,比較常見的有Text,Raised Button,Icon。less
以Text控件爲例(源碼),這個控件沒有能夠被改變的狀態。異步
const Text.rich(
TextSpan(
text: 'Hello', // default text style
children: <TextSpan>[
TextSpan(text: ' beautiful ', style: TextStyle(fontStyle: FontStyle.italic)),
TextSpan(text: 'world', style: TextStyle(fontWeight: FontWeight.bold)),
],
),
)
複製代碼
Text使用一個構造函數進行初始化,初始化時設置一些屬性用於構建控件和控制顯示內容。函數
父控件經過設置alignment、direction、text,來控制本身的顯示,和管理子控件的顯示。ui
那何時該選擇使用stateless的控件呢?spa
例子一: 建立一個自定義的ProgressBar控件,使用的時候經過幾個參數初始化就能展示給用戶。這個控件不須要保留任何狀態,它將被添加到父控件的控件樹中,或者從父控件的控件樹中移除,它的父控件經過管理本身的狀態來控制ProgressBar的顯示或隱藏。code
例子二: 建立一個內容列表中的列表子控件,好比一個蛋糕列表,蛋糕就是這個控件。這個控件將被填入蛋糕的信息,用於展現蛋糕。但這個控件不會保留狀態,它只是使用填充的數據,經過父控件的設置來展現給用戶。orm
從這些例子中能夠看出,stateless的控件是非動態的。它只須要將數據傳入其中,也就是說它只能經過構造函數傳入的數據來控制如何顯示。
Statefule widgets是Stateless widgets的對立面,它是動態的。它能夠被隨時的、動態的修改內容,不像Stateles widgets只能經過構造函數設置。改變的方式多是用戶的輸入,異步的響應或者對另外一個狀態的變化作出反應。
在Flutter中,比較常見的有Image、Form、Checkbox等。
以Image爲例(源碼),Image控件的源文件看起來略有不一樣,它是繼承自StatefulWidget類,也能夠經過構造函數傳入數據來進行初始化,這些都和StatelessWidget相同。
不一樣的地方是,這個控件中多了一個createState
方法(源碼)
_ImageState createState() => new _ImageState();
複製代碼
這個覆寫的方法用來爲控件建立狀態。不用深刻Image如何運做的源碼,就能夠發現_ImageState是用來保存不一樣的屬性。
ImageStream _imageStream;
ImageInfo _imageInfo;
bool _isListeningToStream = false;
bool _invertColors;
複製代碼
ImageInfo
用來爲控件加載實際圖片的屬性。
_handleImageChanged
函數(源碼)中使用了State類的setState函數,來表示狀態發生了變動。
setState(() {
_imageInfo = imageInfo;
});
複製代碼
當發生了狀態變動時,控件將根據新狀態從新構建,也就是說控件將加載更新後的imageInfo圖片數據。這就是Image的動態行爲的表現方式,它會一直監聽圖片引用,當引用放生變化時,它的狀態也會改變。所以Image控件管理着它本身的狀態,不依賴於父控件。
例子一: 建立一個控件用來顯示一個記錄是否被用戶添加了書籤。這個能夠點擊的控件將保留一個isBookmarked
的屬性,當控件被點擊的時候,它的狀態將會被修改,在控件的build
函數中將會爲記錄設置上已經「已經添加過書籤」的標誌。
例子二: 建立一個控件用來保存當前被選中的記錄數量,當點擊「+」按鈕的時候將會增長被選中的記錄數量。這個控件將保存一個數量的狀態,每次點擊「+」按鈕時,新的數量都會記錄到State中,而且在build
函數中更新顯示爲新的數量。