简介
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
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢送关注我的公众号:「程序那些事」, 懂技术,更懂你!