打开抽屉菜单时重建脚手架主体

2023-12-11

我有一个有状态的小部件,它构建了一个脚手架。我在脚手架中使用一个抽屉作为侧面菜单。此外,Scaffold 的主体是一个 FutureBuilder,它从 firestore 数据库获取数据并将信息显示在主体的卡片中。打开抽屉时似乎出现问题,导致主体被重建,FutureBuilder 中的 future 再次查询数据。当抽屉被弹出时,这种情况会再次发生。我在应用程序栏和底部导航栏的脚手架中都有其他按钮来导航到不同的路线。在这些路线中航行时,身体不会被重建。谁能帮忙解释为什么抽屉会发生这种情况?

下面是代码片段。

Thanks

class CustomScaffoldState extends State<CustomScaffold> {

Widget build(BuildContext context) {

  return Scaffold(
    drawer: sideMenu(widget.username),

    body: FutureBuilder(
          future: getData(),
          builder: (context, snapshot) {
             if (snapshot.connectionState == ConnectionState.done) {
                 //return the Card with Info
               }
             if (snapshot.hasError) {
                print('Error');
                 }
             else{
                //return a CircularProgressIndicator
                 }
            }
           ));

//appbar and bottomNavigation bar also implemented
}
}

当抽屉或软键盘打开时屏幕状态发生变化,有时会自动重新加载构建方法,请检查这个链接了解更多信息。

构建方法的设计方式应该是纯净/无副作用的。这是因为许多外部因素可以触发新的小部件构建,例如:

路由弹出/推送 屏幕大小调整,通常是由于键盘外观或方向变化 父部件重新创建了其子部件 小部件依赖的 InheritedWidget (Class.of(context) 模式) 更改 这意味着 build 方法不应触发 http 调用或修改任何状态。

这与问题有什么关系?

您面临的问题是您的构建方法有副作用/不纯粹,使得无关的构建调用变得麻烦。

您不应该阻止构建调用,而应该使构建方法变得纯粹,以便可以随时调用它而不会产生影响。

在您的示例中,您需要将您的小部件转换为 StatefulWidget,然后将该 HTTP 调用提取到您的状态的 initState 中:

class Example extends StatefulWidget {
  @override
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
  Future<int> future;

  @override
  void initState() {
    future = Future.value(42);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: future,
      builder: (context, snapshot) {
        // create some layout here
      },
    );
  }
}

我已经知道了。我来这里是因为我真的想优化重建

也可以使一个小部件能够重建,而无需强迫其子部件也进行构建。

当小部件的实例保持不变时; Flutter 不会故意重建孩子。这意味着您可以缓存小部件树的部分内容以防止不必要的重建。

最简单的方法是使用 dart const 构造函数:

@override
Widget build(BuildContext context) {
  return const DecoratedBox(
    decoration: BoxDecoration(),
    child: Text("Hello World"),
  );
}

多亏了 const 关键字,即使 build 被调用数百次,DecoratedBox 的实例也将保持不变。

但您可以手动实现相同的结果:

@override
Widget build(BuildContext context) {
  final subtree = MyWidget(
    child: Text("Hello World")
  );

  return StreamBuilder<String>(
    stream: stream,
    initialData: "Foo",
    builder: (context, snapshot) {
      return Column(
        children: <Widget>[
          Text(snapshot.data),
          subtree,
        ],
      );
    },
  );
}

在此示例中,当 StreamBuilder 收到新值通知时,即使 StreamBuilder/Column 进行重建,子树也不会重建。发生这种情况是因为,由于关闭,MyWidget 的实例没有改变。

这种模式在动画中被大量使用。典型用途是 AnimatedBuilder 和所有过渡,例如 AlignTransition。

您还可以将子树存储到类的字段中,但不推荐这样做,因为它会破坏热重载功能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

打开抽屉菜单时重建脚手架主体 的相关文章

随机推荐

  • Angular 2打字稿:无法读取未定义的属性newLine

    我正在使用 Angular CLI 来运行 Angular 2 为了运行 我在所有 Angular 2 项目中出现模块构建失败 无法读取未定义的属性 newLine 错误后 在命令提示符中执行 ng 服务 Module build fail
  • python/pandas:使用正则表达式删除字符串中方括号中的任何内容

    使用 pandas 数据框尝试清理类似的列 12 342 to 12342并将该列设置为 int 或 float 虽然找到了一排736 4 所以我必须删除方括号内的所有内容 包括方括号 到目前为止的代码 df2 Average Monthl
  • 导航菜单 CSS 加载缓慢,导致其垂直对齐几秒钟?

    我的 ASP NET 项目的 site master 文件中有一个常规导航菜单 我将我的应用程序保留在服务器中 但是当我启动应用程序或进行回发时 我的导航菜单会垂直对齐几秒钟 当页面完全加载时 它会再次水平排列 我该如何解决这个问题 不是必
  • 当另一个 div 打开时,我需要什么代码来折叠另一个 div?

    我使用一段简单的代码来使 div 折叠 就是这样 我需要添加什么代码才能使其识别何时打开一个 div 并折叠前一个 div 这是我要使用的链接 a href Link 1 a
  • 姓名和电子邮件实体的空响应

    我尝试了内置变量 用户 方法 user name and user email在 API AI 的文本响应中 问候用户并显示电子邮件 ID 是否有内置变量名用户 示例 用户使用 Gmail 注册 Response Code I had tr
  • Pytest 模块未找到错误

    即使我使用 Python 工作这么久 我仍然偶尔会遇到包结构的问题 我正在尝试跑步 pipenv run pytest从下面的目录结构的根 即 上面 src src physics init py pathing py road tests
  • Laravel reCaptcha 集成

    我想在我的 Laravel 项目中实现 reCaptchawithout使用 Laravel 包 我尝试过使用经典的 reCaptcha V2 它可以工作 但我想改为实现不可见的 reCaptcha 所以我做的是这样的
  • Python Numpy One 热销区域

    制作这个 One Hot 编码矩阵的最佳方法是什么 array 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 0 as array 0 0 1 2 1 0 换句话说 如何解码 One Hot 数组 Use np arg
  • Android-显示自定义对话框

    在我的 Android 应用程序中 我使用自定义对话框 当我尝试显示对话框时 它会导致错误 我不知道自己做错了什么 我真的很困惑 这是我的代码 protected Dialog onCreateDialog int id Dialog di
  • python threading.timer 设置程序运行超时的时间限制

    我有一些与在 Python 中设置函数的最大运行时间相关的问题 事实上 我想用pdfminer来转换 pdf文件到 txt 问题是 很多时候 某些文件无法解码并且需要很长时间 所以我想设置threading Timer 将每个文件的转换时间
  • TCL 在字符串中设置特殊字符

    我想在 TCL 中将以下错误消息设置为变量 并与来自网络交换机的错误消息进行比较 绕过特殊字符 使用 插槽 端口 或 端口名称 或 插槽 或 我尝试用这种方式 set x Use slot port or portname or slot
  • 在日历应用程序中对重复事件进行建模的最佳方法是什么? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 我正在构建一个需要支持重复事件的组日历应用程序 但我想出的用于处理这些事件的所有解决方案似乎都是黑客 我可以限制一个人可以看到的距离 然后立即生成所有事件 或者 我可以将事件存储为重复事件
  • 如何禁用“调试”在 package.json 中显示

    如何禁止在上面的 package json 中显示概述的 调试 提示scripts部分 设置为 debug javascript codelens npmScripts never 由于它显示为scripts我搜索的 package jso
  • 将项目标记为特定类别

    我想根据项目中的文本将项目标记为特定类别 我有以下代码 Sub ProcessRSS Read RSS items and process the usful ones Dim objList As Object Dim objItem A
  • Coldfusion 9 使用哪个版本的 iText?

    ColdFusion 9 使用哪个版本的 iText 并不明显 有任何想法吗 ColdFusion 9 0 1 附带 iText 2 1 0 由 lowagie com 提供 您可以在此处找到 ColdFusion 脚本来确定版本 http
  • 如何计算VBA中一个字符串出现在另一个字符串中的次数?

    如何计算 Access VBA 中一个字符串出现在另一个字符串中的次数 例如 我如何计算 The Quick Brown Fox Jumps Over the Lazy Dog 中 The 出现了多少次 因为您对子字符串 区分大小写没问题
  • 从 forEach 推送对象后数组保持为空

    需要帮助 我遇到数组保持空的问题从 forEach 推送对象后 我是否错过了什么 这是代码 const allStatus result forEach async element gt const count await BpCandid
  • 使用 Mac App Store 中 Safari 组件的应用程序的导出合规性

    我正在向 Mac App Store 提交一个应用程序 该应用程序使用 Safari 组件来显示网页 我被问到这个问题 您的应用程序是否设计为使用加密技术 或者是否包含或合并加密技术 即使您的应用程序仅使用 iOS 或 OS X 中提供的加
  • Swift - 整数转换为小时/分钟/秒

    我有一个 有点 关于时间转换的基本问题Swift 我有一个整数 我想将其转换为小时 分钟 秒 Example Int 27005会给我 7 Hours 30 Minutes 5 Seconds 我知道如何在 PHP 中执行此操作 但可惜 S
  • 打开抽屉菜单时重建脚手架主体

    我有一个有状态的小部件 它构建了一个脚手架 我在脚手架中使用一个抽屉作为侧面菜单 此外 Scaffold 的主体是一个 FutureBuilder 它从 firestore 数据库获取数据并将信息显示在主体的卡片中 打开抽屉时似乎出现问题