简介

flutter中有很多种Builder,虽然所有的builder都是构造器,但是不同的builder之间还是有很多差距的。今天我们来详细介绍一下Builder,LayoutBuilder,StatefulBuilder这几个builder的使用。

Builder

Builder是flutter中最常用的builder,它是一个StatelessWidget,如下所示:

  1. class Builder extends StatelessWidget

我们看下它的构造函数:

  1. const Builder({
  2. Key? key,
  3. required this.builder,
  4. }) : assert(builder != null),
  5. super(key: key);

可以看到Builder和普通的StatelessWidget的最大的差别就是需要传入一个builder属性,这个builder是一个WidgetBuilder类型的属性,

WidgetBuilder是这样定义的:

  1. typedef WidgetBuilder = Widget Function(BuildContext context);

可以看到WidgetBuilder实际上是一个返回Widget的函数,这个函数在Builder被包含在parent's build方法中的时候,会被调用。

那么使用Builder和普通的StatelessWidget有什么区别呢?

我们举个例子,首先是在Scaffold中直接包含一个包括TextButton的Center widget,如下所示:

  1. Widget build(BuildContext context) {
  2. return Scaffold(
  3. body: Center(
  4. child: TextButton(
  5. child: Text('TextButton'),
  6. )
  7. ),
  8. );
  9. }

上面的Center也可以使用Builder来封装:

  1. Widget build(BuildContext context) {
  2. return Scaffold(
  3. body: Builder(
  4. builder: (BuildContext context) {
  5. return Center(
  6. child: TextButton(
  7. child: Text('TextButton'),
  8. ),
  9. );
  10. },
  11. ),
  12. );
  13. }

初看起来两者没有太大的区别,但是不同的是在下面的例子中,我们使用了Builder来构建body。

Builder的builder方法中我们传入了一个context,这个context是当前builder的context,我们可以通过这个context来获取到一些平时比较难获取到的对象。

对于Scaffold来说,它提供了一个of方法,可以根据传入的context来找到离context最近的Scaffold。这也是我们使用builder的目的:

  1. Widget build(BuildContext context) {
  2. return Scaffold(
  3. body: Builder(
  4. builder: (BuildContext context) {
  5. return Center(
  6. child: TextButton(
  7. onPressed: () {
  8. print(Scaffold.of(context).hasAppBar);
  9. },
  10. child: Text('TextButton'),
  11. ),
  12. );
  13. },
  14. ),
  15. );
  16. }

如上,我们可以在builder中,调用Scaffold.of(context)方法来获取对应的Scaffold对象。

如果只是使用普通的StatelessWidget的话,是没法拿到Scaffold对象的。

StatefulBuilder

上一节我们提到的Buidler实际上是一个StatelessWidget,表明builder是无状态的。

而StatefulBuilder则和Builder不同,它是有状态的:

  1. class StatefulBuilder extends StatefulWidget

可以看到StatefulBuilder继承自StatefulWidget。

和Builder很类似,StatefulBuilder也有一个builder属性,不过这个builder属性的类型是StatefulWidgetBuilder:

  1. typedef StatefulWidgetBuilder = Widget Function(BuildContext context, StateSetter setState);

可以看到StatefulWidgetBuilder被调用的时候,不仅传入了BuildContext,还同时调用了setState方法。

StateSetter方法会导致Widget重构。

如果我们创建的widget是一个StatefulWidget的话,那么就可以尝试使用StatefulBuilder来代替:

  1. Widget build(BuildContext context) {
  2. return Center(
  3. child: Builder(
  4. builder: (BuildContext context) {
  5. int clicked = 0;
  6. return Center(
  7. child: StatefulBuilder(
  8. builder: (BuildContext context, StateSetter setState) {
  9. return TextButton(onPressed: (){
  10. setState(() => {clicked = 1 });
  11. },
  12. child: Text('TextButton'));
  13. }),
  14. );
  15. },
  16. ),
  17. );
  18. }

LayoutBuilder

Builder可以传递BuildContext, StatefulBuilder可以传递StateSetter,LayoutBuilder和上面提到的两个Builder很类似,不同的是LayoutBuilder可以提供父widget的大小。

我们先来看下LayoutBuilder的定义:

  1. class LayoutBuilder extends ConstrainedLayoutBuilder<BoxConstraints>

可以看到LayoutBuilder继承的类是不同的。

LayoutBuilder需要传入一个builder属性,这个builder是一个LayoutWidgetBuilder对象:

  1. typedef LayoutWidgetBuilder = Widget Function(BuildContext context, BoxConstraints constraints);

具体的使用方法和Builder很类似,不同的是我们可以根据传入的BoxConstraints来进行对应的逻辑判断。

看一个具体的例子:

  1. class LayoutBuilderApp extends StatelessWidget{
  2. @override
  3. Widget build(BuildContext context) {
  4. return LayoutBuilder(
  5. builder: (BuildContext context, BoxConstraints constraints) {
  6. if (constraints.maxWidth > 500) {
  7. return buildWidget1();
  8. } else {
  9. return buildWidget2();
  10. }
  11. },
  12. );
  13. }
  14. Widget buildWidget1() {
  15. return Center(
  16. child: Container(
  17. height: 700.0,
  18. width: 700.0,
  19. color: Colors.blue,
  20. ),
  21. );
  22. }
  23. Widget buildWidget2() {
  24. return Center(
  25. child: Container(
  26. height: 200.0,
  27. width: 200.0,
  28. color: Colors.yellow,
  29. ),
  30. );
  31. }

上面的例子中,我们根据BoxConstraints的大小,来返回不同的Widget组件。

这在某些情况下是非常有用的。

总结

本文介绍了三个常用的Builder,大家可以仔细体会。

本文的例子:https://github.com/ddean2009/learn-flutter.git

更多内容请参考 www.flydean.com

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

flutter系列之:builder为构造器而生的更多相关文章

  1. Flutter系列博文链接

    Flutter系列博文链接 ↓: Flutter基础篇: Flutter基础篇(1)-- 跨平台开发框架和工具集锦 Flutter基础篇(2)-- 老司机用一篇博客带你快速熟悉Dart语法 Flutt ...

  2. Java - 用builder代替构造器

    静态工厂和够构造器有一个共同的局限性:遇到大量的参数时无法很好的扩展. 先说说构造器. 其实field不多时重叠构造器(telescoping constructor)是个不错的方法,易于编写也易于调 ...

  3. 我的强迫症系列之@Builder和建造者模式

    前言 备受争议的Lombok,有的人喜欢它让代码更整洁,有的人不喜欢它,巴拉巴拉一堆原因.在我看来Lombok唯一的缺点可能就是需要安装插件了,但是对于业务开发的项目来说,它的优点远远超过缺点. 我们 ...

  4. 设计模式实战系列之@Builder和建造者模式

    前言 备受争议的Lombok,有的人喜欢它让代码更整洁,有的人不喜欢它,巴拉巴拉一堆原因.在我看来Lombok唯一的缺点可能就是需要安装插件了,但是对于业务开发的项目来说,它的优点远远超过缺点. 我们 ...

  5. flutter系列之:flutter架构什么的,看完这篇文章就全懂了

    目录 简介 Flutter的架构图 embedder engine Flutter framework Widgets Widgets的可扩展性 Widgets的状态管理 渲染和布局 总结 简介 Fl ...

  6. flutter系列之:构建Widget的上下文环境BuildContext详解

    目录 简介 BuildContext的本质 BuildContext和InheritedWidget BuildContext的层级关系 总结 简介 我们知道Flutter中有两种Widget,分别是 ...

  7. flutter系列之:Material主题的基础-MaterialApp

    简介 为了简化大家的使用,虽然flutter推荐所有的widget都有自己来进行搭建,但是在大框架上面,flutter提供了Material和Cupertino两种主题风格的Widgets集合,大家可 ...

  8. flutter系列之:UI layout简介

    目录 简介 flutter中layout的分类 常用layout举例 总结 简介 对于一个前端框架来说,除了各个组件之外,最重要的就是将这些组件进行连接的布局了.布局的英文名叫做layout,就是用来 ...

  9. Java面向对象系列(5)- 构造器详解

    构造器: 和类名相同 没有返回值 作用: new本质在调用构造器 初始化对象的值 注意点: 定义了有参构造之后,如果想要使用有参构造,必须显示的定义一个无参构造 IDEA快捷键: Alt + Inse ...

随机推荐

  1. python编程思想及对象与类

    目录 编程思想 面向对象 面向过程 对象与类的概念 对象与类的创建 对象的实例化方法-独有数据 编程思想 1.面向对象 1.1. 面向对象前戏 案例:人狗大战 # 需求:人狗大战# 1.'创造'出人和 ...

  2. DS二叉树——二叉树之数组存储

    题目描述 二叉树可以采用数组的方法进行存储,把数组中的数据依次自上而下,自左至右存储到二叉树结点中,一般二叉树与完全二叉树对比,比完全二叉树缺少的结点就在数组中用0来表示.,如下图所示 从上图可以看出 ...

  3. java-循环

    1.循环:反复执行一段相同或相似的代码(逻辑相似或者相同)2.循环三要素: 1.循环变量的初始化 2.循环的条件(以循环变量为基础) 3.循环变量的改变(向着循环的结束变)循环变量:在整个循环过程中所 ...

  4. jQuery使用case记录

    添加元素/内容追加等 元素内: append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 元素外: after() - 在被选元素之后插入内容 before() ...

  5. html页面嵌套其他网站页面的方法

    直接上代码:html页面嵌套其他网站页面的方法 <div> <!--第一种:使用object标签--> <object type="text/html" ...

  6. Linus命令

    参考: https://blog.csdn.net/weixin_44191814/article/details/120091363 vim编辑器 ## Vim基本模式 [对文件进行操作]vim 文 ...

  7. 第六十二篇:Vue的双向绑定与按键修饰符

    好家伙,依旧是vue的基础 1.按键修饰符 假设我们在一个<input>框中输入了12345,我们希望按一下"Esc" 然后删除所有前面输入的内容,这时候,我们会用到按 ...

  8. C语言小游戏:贪吃蛇

    #include <graphics.h> #include <conio.h> #include <stdio.h> #define WIDTH 40 //设置宽 ...

  9. FusionCopmpute之CNA,VRM虚拟机安装

    CNA和VRM安装步骤一样,需要修改的只有IP 按步骤创建 修改自己虚拟机想要存放的位置 需要把自己网络同样配置为仅主机(提前配好) 自己也可以修改至200G 虚拟机只是用多少取多少 CNA可以设置为 ...

  10. with function 语法支持

    通过with子句,我们可以把很多原本需要存储过程来实现的复杂逻辑用一句SQL来进行表达.KingbaseES 从V008R006C004B0021 版本开始,支持 with function 语法.例 ...