【Flutter】Stateful widgets與Stateless widgets

原文

Stateful or Stateless widgets?git

前言

在建立一個Flutter App的時候,會遇到兩種類型的控件github

  1. 有狀態控件(stateful widgets)
  2. 無狀態控件(stateless widgets)

Stateless Widgets

在建立控件的時候,有一些控件不須要管理控件內部狀態,這個時候就能夠選擇無狀態控件。無狀態控件除了用數據初始化之外的時刻,不須要改變它的狀態。bash

在Flutter中,比較常見的有Text,Raised Button,Icon。less

Texture

以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的

那何時該選擇使用stateless的控件呢?spa

例子一: 建立一個自定義的ProgressBar控件,使用的時候經過幾個參數初始化就能展示給用戶。這個控件不須要保留任何狀態,它將被添加到父控件的控件樹中,或者從父控件的控件樹中移除,它的父控件經過管理本身的狀態來控制ProgressBar的顯示或隱藏。code

例子二: 建立一個內容列表中的列表子控件,好比一個蛋糕列表,蛋糕就是這個控件。這個控件將被填入蛋糕的信息,用於展現蛋糕。但這個控件不會保留狀態,它只是使用填充的數據,經過父控件的設置來展現給用戶。orm

從這些例子中能夠看出,stateless的控件是非動態的。它只須要將數據傳入其中,也就是說它只能經過構造函數傳入的數據來控制如何顯示。

Stateful widgets

Statefule widgets是Stateless widgets的對立面,它是動態的。它能夠被隨時的、動態的修改內容,不像Stateles widgets只能經過構造函數設置。改變的方式多是用戶的輸入,異步的響應或者對另外一個狀態的變化作出反應。

在Flutter中,比較常見的有Image、Form、Checkbox等。

Image

以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控件管理着它本身的狀態,不依賴於父控件。

什麼樣的控件是Stateful widgets

例子一: 建立一個控件用來顯示一個記錄是否被用戶添加了書籤。這個能夠點擊的控件將保留一個isBookmarked的屬性,當控件被點擊的時候,它的狀態將會被修改,在控件的build函數中將會爲記錄設置上已經「已經添加過書籤」的標誌。

例子二: 建立一個控件用來保存當前被選中的記錄數量,當點擊「+」按鈕的時候將會增長被選中的記錄數量。這個控件將保存一個數量的狀態,每次點擊「+」按鈕時,新的數量都會記錄到State中,而且在build函數中更新顯示爲新的數量。

相關文章
相關標籤/搜索