简介
flutter中有很多种Builder,尽管所有的builder都是结构器,然而不同的builder之间还是有很多差距的。明天咱们来具体介绍一下Builder,LayoutBuilder,StatefulBuilder这几个builder的应用。
Builder
Builder是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')); }), ); }, ), ); }
LayoutBuilder
Builder能够传递BuildContext, StatefulBuilder能够传递StateSetter,LayoutBuilder和下面提到的两个Builder很相似,不同的是LayoutBuilder能够提供父widget的大小。
咱们先来看下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{ @override Widget 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, ), ); }
下面的例子中,咱们依据BoxConstraints的大小,来返回不同的Widget组件。
这在某些状况下是十分有用的。
总结
本文介绍了三个罕用的Builder,大家能够认真领会。
本文的例子:https://github.com/ddean2009/learn-flutter.git
更多内容请参考 www.flydean.com
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢送关注我的公众号:「程序那些事」,懂技术,更懂你!