flutter系列之:builder為構造器而生

目錄

  • 簡介
  • Builder
  • StatefulBuilder
  • LayoutBuilder
  • 總結
簡介flutter中有很多種Builder,雖然所有的builder都是構造器,但是不同的builder之間還是有很多差距的 。今天我們來詳細介紹一下Builder,LayoutBuilder,StatefulBuilder這幾個builder的使用 。
BuilderBuilder是flutter中最常用的builder,它是一個StatelessWidget,如下所示:
class Builder extends StatelessWidget我們看下它的構造函數:
const Builder({Key? key,required this.builder,}) : assert(builder != null),super(key: key);可以看到Builder和普通的StatelessWidget的最大的差別就是需要傳入一個builder屬性,這個builder是一個WidgetBuilder類型的屬性,
WidgetBuilder是這樣定義的:
typedef WidgetBuilder = Widget Function(BuildContext context);可以看到WidgetBuilder實際上是一個返回Widget的函數,這個函數在Builder被包含在parent's build方法中的時候,會被調用 。
那么使用Builder和普通的StatelessWidget有什么區別呢?
我們舉個例子,首先是在Scaffold中直接包含一個包括TextButton的Center widget , 如下所示:
Widget build(BuildContext context) {return Scaffold(body: Center(child: TextButton(child: Text('TextButton'),)),);}上面的Center也可以使用Builder來封裝:
Widget build(BuildContext context) {return Scaffold(body: Builder(builder: (BuildContext context) {return Center(child: TextButton(child: Text('TextButton'),),);},),);}初看起來兩者沒有太大的區別,但是不同的是在下面的例子中 , 我們使用了Builder來構建body 。
Builder的builder方法中我們傳入了一個context,這個context是當前builder的context,我們可以通過這個context來獲取到一些平時比較難獲取到的對象 。
對于Scaffold來說 , 它提供了一個of方法,可以根據傳入的context來找到離context最近的Scaffold 。這也是我們使用builder的目的:
Widget build(BuildContext context) {return Scaffold(body: Builder(builder: (BuildContext context) {return Center(child: TextButton(onPressed: () {print(Scaffold.of(context).hasAppBar);},child: Text('TextButton'),),);},),);}如上,我們可以在builder中 , 調用Scaffold.of(context)方法來獲取對應的Scaffold對象 。
如果只是使用普通的StatelessWidget的話,是沒法拿到Scaffold對象的 。
StatefulBuilder上一節我們提到的Buidler實際上是一個StatelessWidget,表明builder是無狀態的 。
而StatefulBuilder則和Builder不同,它是有狀態的:
class StatefulBuilder extends StatefulWidget可以看到StatefulBuilder繼承自StatefulWidget 。
和Builder很類似 , StatefulBuilder也有一個builder屬性 , 不過這個builder屬性的類型是StatefulWidgetBuilder:
typedef StatefulWidgetBuilder = Widget Function(BuildContext context, StateSetter setState);可以看到StatefulWidgetBuilder被調用的時候,不僅傳入了BuildContext,還同時調用了setState方法 。
StateSetter方法會導致Widget重構 。
如果我們創建的widget是一個StatefulWidget的話,那么就可以嘗試使用StatefulBuilder來代替:
Widget build(BuildContext context) {return Center(child: Builder(builder: (BuildContext context) {int clicked = 0;return Center(child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {return TextButton(onPressed: (){setState(() => {clicked = 1 });},child: Text('TextButton'));}),);},),);}LayoutBuilderBuilder可以傳遞BuildContext,StatefulBuilder可以傳遞StateSetter,LayoutBuilder和上面提到的兩個Builder很類似,不同的是LayoutBuilder可以提供父widget的大小 。
【flutter系列之:builder為構造器而生】我們先來看下LayoutBuilder的定義:
class LayoutBuilder extends ConstrainedLayoutBuilder<BoxConstraints>可以看到LayoutBuilder繼承的類是不同的 。
LayoutBuilder需要傳入一個builder屬性,這個builder是一個LayoutWidgetBuilder對象:
typedef LayoutWidgetBuilder = Widget Function(BuildContext context, BoxConstraints constraints);具體的使用方法和Builder很類似 , 不同的是我們可以根據傳入的BoxConstraints來進行對應的邏輯判斷 。
看一個具體的例子:
class LayoutBuilderApp extends StatelessWidget{@overrideWidget build(BuildContext context) {return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {if (constraints.maxWidth > 500) {return buildWidget1();} else {return buildWidget2();}},);}Widget buildWidget1() {return Center(child: Container(height: 700.0,width: 700.0,color: Colors.blue,),);}Widget buildWidget2() {return Center(child: Container(height: 200.0,width: 200.0,color: Colors.yellow,),);}

推薦閱讀