StatefulBuilder 和 Builder

本文介绍了Flutter中的StatefulBuilder和Builder组件,前者用于动态更新局部状态并重建widget树,后者用于获取新的BuildContext以隔离环境影响。作者通过实际案例展示了两者在对话框状态管理中的应用和区别。
摘要由CSDN通过智能技术生成

前言

果然了解的越多,越发现自己狗屁都不是。StatefulBuilderBuilder 之前真的不知道。还是在 对话框状态管理
中了解到了这两个东西。

简介

以下内容来自通义灵码

在Flutter中,StatefulBuilderBuilder 都是用来动态构建 widget 树的组件,但它们在处理状态管理和构建上下文方面有所不同:

StatefulBuilder

  • StatefulBuilder 是一个特殊的 widget,主要用于那些本身不是 StatefulWidget 但却需要在构建过程中更改和反应状态变化的场景。它接收一个 builder 函数作为参数,这个函数会在状态更改时被调用并重新构建其内部 widget 树。
  • 使用 StatefulBuilder 时,你可以直接在其 builder 方法内调用提供的 _setState 参数来更新局部状态,并立即触发内部 widget 树的重建,而无需刷新整个页面或父级 StatefulWidget 的状态。
StatefulBuilder(
  builder: (BuildContext context, void Function(void Function()) setState) {
    bool isChecked = ...; // 可变状态
    return Checkbox(
      value: isChecked,
      onChanged: (bool newValue) {
        setState(() {
          isChecked = newValue;
        });
      },
    );
  },
);

Builder

  • Builder widget 不具备自身的状态管理能力,但它主要用于构建作用域内的BuildContext,特别是在涉及到InheritedWidget、Theme、Navigator等需要访问新构建环境的场景下。
  • Builder 主要用于将现有的 build 方法内部的上下文传递给其内部的 builder 函数,这样就可以在新的上下文中构建子 widget。这有助于隔离环境影响,尤其是在处理多个嵌套的 Consumer, StreamBuilder 或者 InheritedWidget 时。
Builder(
  builder: (BuildContext context) {
    // 这里可以使用新的BuildContext来构建子widget
    return Container(...);
  },
)

简而言之:

  • StatefulBuilder 允许你在没有独立 StatefulWidget 的情况下,在 widget 树的任何位置动态地更新状态。
  • Builder 则是为了获取或创建一个新的构建上下文,以便于在不同的环境中正确构建和访问 widget。它本身不涉及状态管理,更多关注的是构建环境的控制与传递。

案例

上面那篇文章里有对应的例子。这里也只是对其记录和学习。

    Future<bool?> showDeleteDialog() {
      // 记录是否选中
      bool isChecked = true;

      return showDialog<bool>(
          context: context,
          builder: (context) {
            return AlertDialog(
              title: const Text("提示"),
              content: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                // 高度设置为最小
                mainAxisSize: MainAxisSize.min,
                children: [
                  const Text("是否删除?"),
                  Row(
                    children: [
                      const Text("同时删除子目录?"),
                      Checkbox(
                          value: isChecked,
                          onChanged: (bool? value) {
                            isChecked = value!;
                          })
                    ],
                  )
                ],
              ),
              actions: [
                TextButton(
                    onPressed: () {
                      Navigator.pop(context, false);
                    },
                    child: const Text("取消")),
                TextButton(
                    onPressed: () {
                      // 返回选中状态
                      Navigator.pop(context, isChecked);
                    },
                    child: const Text("确定")),
              ],
            );
          });
    }

在这里插入图片描述

可以看出,UI没有被更新,文章中也给出了解释:

对话框也是通过路由的方式来实现的,那么上面的代码实际上就等同于企图在父路由中调用setState来让子路由更新,这显然是不行的!简尔言之,根本原因就是context不对。

解决方法那就是使用 StatefulBuilderBuilder 获取到独立的context

Row(
  children: [
    const Text("同时删除子目录?"),
    StatefulBuilder(builder: (context, setState) {
      return Checkbox(
          value: isChecked,
          onChanged: (bool? value) {
            setState(() {
              isChecked = value!;
            });
          });
    })
  ],
)
Row(
   children: [
     const Text("同时删除子目录?"),
     Builder(builder: (context) {
       return Checkbox(
           value: isChecked,
           onChanged: (bool? value) {
             (context as Element).markNeedsBuild();
             isChecked = value ?? false;
           });
     })
   ],
 )

在这里插入图片描述
StatefulBuilder中会提供一个setState用来更新局部状态,触发UI更新。
Builder 则是为了获取或创建一个新的构建上下文,调用ElementmarkNeedsBuild()方法来进行局部状态更新。

课程首先介绍了Flutter的主要知识,通过4个案例消化吸收知识点。并通过手把手一步步带您完成一个【我的备忘录】APP项目,使得您真正认识Flutter在实际项目中的优势。  通过本课程学习您可以学习到Flutter技术如下知识:第1章 Flutter概述知识点:移动应用开发现状、移动应用开发类型、Hybrid与移动跨平台开发策略、Flutter是什么?、Flutter特点、Flutter体系结构。第2章 Flutter开发环境搭建知识点:基于Windows的Android开发环境、基于macOS的iOS开发环境、IDE开发工具设置。第3章 Flutter基础知识点:完成一个Flutter程序、一切都是组件(Widget)、组件分类、使用图片和图标资源、使用文本组件、增加调试组件工具。第4章 布局组件知识点:Flutter布局概述、容器布局(Container)、行(Row)、列(Column)布局、层叠布局、ListView、GridView。第5章 Material风格组件知识点:按钮、输入框、复选框、单选按钮、开关按钮、滑块。第6章 iOS Cupertino风格组件知识点:iOS Cupertino页面、Cupertino按钮、Cupertino开关按钮、Cupertino滑块、Cupertino分段控件。第7章 状态管理知识点:状态管理概述、局部状态管理、全局状态管理。第8章 导航知识点:导航概述、面包屑导航、标签导航、页面组件分散在不同文件中、全局状态管理与导航。第9章 工程依赖管理知识点:工程依赖管理概述、pub依赖管理工具。第10章 数据存储知识点:Flutter数据存储策略、键值对数据存储、文件数据存储、SQLite数据存储、示例:数据CRUD操作。第11章 网络通信知识点:搭建自己的Web服务器、使用http包、示例:城市信息列表。第12章 项目实战:我的备忘录APP知识点:备忘录APP项目说明、备忘录项目后台Web服务API说明、备忘录APP项目分析与设计、初始化工程、持久层实现、表示层实现。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无知的小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值