0x00 無狀態元件和狀態元件
widget是fltter介面開發中的基礎控制元件,如同ios中的uiview這種地位,所謂萬物皆widget。
widget有分為statelessWidget和statefulWidget,這兩者是什麼區別呢。一句話就是說statelesswidget用來展示無狀態的檢視,而statefulwidget用來展示可互動的,動態的檢視。
到此基本的結論已經出來了,那麼state究竟是怎麼實現狀態的更新的?
原文發表地址 flutterdev.top
0x01 UI程式設計正規化
iOS和安卓開發採用的是指令式程式設計正規化,而flutter、前端的VUE,小程式開發採用的是宣告式。
如 ios
UILable * lable = [UILable new];
label.text = "hello world";
複製程式碼
這就是命令式,直接對控制元件中的屬性進行精準高效的賦值控制。
然而flutter如下
class BgChangeView extends StatefulWidget {
@override
_BgChangeViewState createState() => _BgChangeViewState();
Color color = Colors.red;
}
class _BgChangeViewState extends State<BgChangeView> {
int count = 10;
void _incrementCounter() {
setState(() {
count = count>255 ? 0 :count + 10;
widget.color = Color.fromARGB(count, 0x00, 0xff, 0xff);
print("state refresh count ${count}");
});
}
@override
Widget build(BuildContext context) {
return Container(
width: 100,
height: 100,
child: RaisedButton(onPressed: _incrementCounter,
color: widget.color,
),
);
}
}
複製程式碼
將color指定給raisebutton,color在state中更新了,從而更新了raisebuttom的背景顏色
0x02 如何實現
state是表示檢視的狀態,當setState觸發當前檢視及其子檢視的銷燬重建,從父檢視到子檢視,從上到下的順序重建。
猜測內部state的實現
其實state是負責銷燬重建的,在重建的過程中重新對widget樹一級級生成,並把外部的資料重新對widget進行賦值操作,因為內部機制小部件重建的效率很高,幾乎肉眼看不到它銷燬的過程,但是如果對於root檢視頻繁進行state的操作,會帶來很大的效能開銷,卡頓,cpu,gpu使用率過高等情況。這也是宣告式程式設計一個弊端。使用中需要進來避免過多的setState的操作。
flutter engine內部當然會優化這部分的效能,每次重建之後之前申請的widget或randerobject使用的空間不會一個個的清空釋放,而是採取一直滑動壓縮
的方式進行清理。如下圖所示
- flutter將記憶體區域分為兩部分,活躍空間和不活躍空間
- 使用者使用app,flutter在活躍空間不斷申請記憶體空間
- 直到獲取空間分配滿了
- 檢查活躍空間中活躍的物件,將活躍的和其所依賴的物件一併標誌
- 在app空閒時將活躍的物件移動到不活躍區域,此時活躍的物件中間沒有不活躍的區域了
- 將不活躍的區域和活躍區域交換狀態
參考文章
- flutter核心技術實戰 time.geekbang.org/column/arti…
- flutter記憶體技術 www.helloted.com/flutter/201…