如何调用无状态小部件的重建?

2024-01-02

Context

我有两个无状态小部件(页面):HomePage and DetailsPage。显然应用程序启动并启动HomePage。用户可以按下一个按钮来导航到DetailsPage with a Navigator.pop()按钮导航回到HomePage.

我知道什么时候DetailsPage已完成与使用.whenComplete()方法。正是在这一点上我想重建HomePage widget.

Code

这是我行为的最小再现。

main.dart
import 'package:example/home.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: HomePage());
  }
}
home.dart
import 'package:example/details.dart';
import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  static const name = 'Home Page';
  const HomePage() : super();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: MaterialButton(
          color: Colors.blue,
          textColor: Colors.white,
          child: Text(name),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: DetailsPage.builder),
            ).whenComplete(() => print('Rebuild now.'));
          },
        ),
      ),
    );
  }
}
details.dart
import 'package:flutter/material.dart';

class DetailsPage extends StatelessWidget {
  static const name = 'Details Page';
  static WidgetBuilder builder = (BuildContext _) => DetailsPage();
  const DetailsPage();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(name),
            MaterialButton(
              color: Colors.blue,
              textColor: Colors.white,
              child: Text('Go Back'),
              onPressed: () => Navigator.pop(context),
            ),
          ],
        ),
      ),
    );
  }
}

Question

我如何调用这个无状态小部件的重建(HomePage)在.whenComplete()方法回调?


您可以按如下方式强制重建小部件树:

class RebuildController   {
  final GlobalKey rebuildKey = GlobalKey();
  
  void rebuild() {
    void rebuild(Element el) {
      el.markNeedsBuild();
      el.visitChildren(rebuild);
    }
    (rebuildKey.currentContext as Element).visitChildren(rebuild);
  }

}

class RebuildWrapper extends StatelessWidget  {
  
  final RebuildController controller;
  final Widget child;

  const RebuildWrapper({Key? key, required this.controller, required this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) => Container(
    key: controller.rebuildKey,
    child: child,
  );

}

就你而言,

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final RebuildController controller = RebuildController();

  MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: RebuildWrapper(
        controller: controller,
        child: HomePage(
          rebuildController: controller,
        ),
      ),
    );
  }
}

class HomePage extends StatelessWidget {

  static const name = 'Home Page';
  final RebuildController rebuildController;

  const HomePage({Key? key, required this.rebuildController}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('Hello there!');
    return Scaffold(
      body: Center(
        child: MaterialButton(
          color: Colors.blue,
          textColor: Colors.white,
          child: const Text(name),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: DetailsPage.builder),
            ).whenComplete(rebuildController.rebuild);
          },
        ),
      ),
    );
  }
  
}

class DetailsPage extends StatelessWidget {
  static const name = 'Details Page';
  static WidgetBuilder builder = (BuildContext _) => const DetailsPage();

  const DetailsPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(name),
            MaterialButton(
              color: Colors.blue,
              textColor: Colors.white,
              child: const Text('Go Back'),
              onPressed: () => Navigator.pop(context),
            ),
          ],
        ),
      ),
    );
  }
}

class RebuildController   {
  final GlobalKey rebuildKey = GlobalKey();
  
  void rebuild() {
    void rebuild(Element el) {
      el.markNeedsBuild();
      el.visitChildren(rebuild);
    }
    (rebuildKey.currentContext as Element).visitChildren(rebuild);
  }

}

class RebuildWrapper extends StatelessWidget  {
  
  final RebuildController controller;
  final Widget child;

  const RebuildWrapper({Key? key, required this.controller, required this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) => Container(
    key: controller.rebuildKey,
    child: child,
  );

}

但是强制重建无状态小部件是不自然的,因为它们不应该被重建。你应该使用有状态的小部件 https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html或其他状态管理 https://docs.flutter.dev/development/data-and-backend/state-mgmt/options解决方案,以便您的主页只会更新有意义的状态改变。

来源 -这个答案 https://stackoverflow.com/a/58513635/17673002

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

如何调用无状态小部件的重建? 的相关文章

  • 如何在flutter app android中添加Startapp广告?

    我想用其他广告更改 AdMob 广告 一些个人问题 如何在flutter app android中添加Startapp广告 有什么方法可以将启动广告添加到我的 flutter 应用程序 android 中 StartApp 现已更名为 St
  • getApplicationDocumentsDirectory 在 flutter 桌面(Windows)上不起作用

    如何在 Windows 上的 flutter 桌面上保存和打开文件 getApplicationDocumentsDirectory 不适用于 Windows 应用程序的 flutter 桌面 Future
  • Flutter - 迭代对象键和值

    我有和反对 我想知道是否有一种简单的方法来迭代它的键和值 class Post String id String title String article Post this id this title this article 那没有 你
  • 错误:无法在 pubspec.yaml 中找到目录条目

    我正在尝试在我的 flutter 应用程序中添加外部包中的资产 正如这里提到的 https flutter dev docs development ui assets and images bundling of package asse
  • Flutter 本地通知图标未显示

    我面临着一个非常常见的问题 但我看到的解决方案没有帮助我 所以 我正在尝试显示本地通知 除了图标之外一切正常 按照包的文档 我向可绘制对象添加了一个图标 但它不起作用 这是我的文件夹的结构和我想显示的图像 这是我的初始化代码 我尝试了很多事
  • Flutter 如何制作自定义Tab Bar?

    我正在 Flutter 中构建应用程序 现在我想创建自定义选项卡栏 我想要一个如图所示的标签栏 这是一个使用的解决方案CustomPainter 标签绘制器 非常基本的路径画家来绘制选项卡的背景 class TabPainter exten
  • 将标头添加到 SecureSocket 或 SecurityContext 到 WebSpcket

    WebSocket 可以选择向请求添加标头 但不能向其中添加 SecurityContext SecureSocket 具有 SecurityContext 因此我可以添加 ssl 证书 但无法添加标头 对此有什么想法吗 UPDATE 我正
  • TextFormString 验证器的多行字符串

    In my TextFormString对于密码字段我有validator返回一个字符串 问题是这样的String太长了 不适合屏幕 我想让它成为多行 但我找不到如何做到这一点 我尝试设置宽度Container this TextFormS
  • 禁用向下拖动以关闭 showModalBottomSheet

    如何在底部表单模态中禁用 转义向下拖动手势 以便用户可以在模态中进行交互而不会意外关闭模态 下面用实际的模态底部表进行了更新 return showModalBottomSheet context context builder Build
  • 更改 Flutter Web 应用程序中的屏幕尺寸

    我正在使用 Flutter 构建一个 Web 应用程序 但我想模仿 iPhone 屏幕视图 我知道调整窗口大小可以达到这种效果 但是有没有办法将所有内容包装在手机屏幕图形的框架中 或者更改 MaterialApp 的尺寸 使其包含在手机屏幕
  • Flutter Firestore 查询嵌套子集合

    我正在尝试查询 Firebase 中的子集合 但我总是得到一个空列表 这是我的查询 Firestore instance collection messages where idFrom isEqualTo userID snapshots
  • Flutter textfield Flutter RTL光标位置问题n-1

    我不知道这个问题是否是老问题 但我尝试了所有方法都没有成功 在输入字段中选择字母 n 时出现的问题 光标跳转到 n 1 包含视频中显示的问题 仅在 RTL 中存在问题 该链接包含问题的代码和视频 代码 链接在这里 https github
  • 颤振文本小部件仅显示最后一个条目

    我正在尝试在 flutter 中创建日历 目前我正在实施这些活动 为了测试这一点 我创建了一个方法来检查当前日期 即创建行的时间 是否有事件 如果是这种情况 则会在表示内容的容器中打印 x 整个事情只是第一次测试 看它是否在原则上有效 当我
  • Flutter 命令删除 .pub-cache 文件夹中的包

    如何删除flutter包 pub cache文件夹 当我们给予flutter clean 它将删除当前目录中的build文件夹 我们可以手动删除 但是我的要求是删除里面的包 pub cache使用命令的文件夹 要清除全局 PUB CACHE
  • 错误:未为类“BuildContext”定义方法“inheritFromWidgetOfExactType”

    今天编译flutter项目的时候出现了这样的错误 This will generate a JSON format file containing all messages that need to be translated pub ca
  • 如何使用 Firebase_Auth 和 Flutter 登录 Twitter

    一个人应该如何编程使用 Twitter 登录特征使用firebase auth https pub dev packages firebase auth和颤动 我看到一些使用的例子flutter twitter login https pu
  • 如何根据有效(@mentions)和所有主题标签更改文本颜色?

    我想在文本中用不同颜色显示主题标签和有效提及 我得到了这段代码的帮助 该代码仅适用于主题标签 RichText convertHashtag String text List
  • 使用 Visual Studio Code 在 Flutter 上运行 Gradle 时出错

    我正在使用 Windows 10 Visual Studio Code 我尝试在编写代码后运行我的代码 这就是它之后向我展示的内容 在调试模式下在 TECNO Camon CX 上启动 lib main dart 运行 Gradle 时出错
  • 如何为发布而不是调试创建密钥库?扑

    我按照使用此网站部署 flutter 的步骤进行操作https flutter io android release https flutter io android release 当我运行 flutter build apk 时出现此错
  • 如何在 Flutter App 中按时间注销?

    如果用户在登录后对应用程序没有反应或不活动超过 5 分钟 我需要从应用程序中注销用户 该应用程序将转到主登录页面 我尝试实施给定的解决方案here https stackoverflow com questions 52602606 how

随机推荐

  • p5.j​​s 中的上下移动(并使用 WASD)

    在p5中如何使用键盘让角色移动 我的意思是 不仅仅是向左和向右 我还想使用 WASD 键 我用过这个 形状作为占位符 https editor p5js org TheDiamondfinderYT present 8ZqV2LsVB ht
  • 如何用Pickle存储自我价值?

    class Player def init self self money 0 self level 0 self xp 0 self xp until level 20 self taxi car Cabbie self busines
  • 在 Jenkins 中配置 GitLab 存储库

    我正在尝试配置 Jenkins 在 Windows Server 2008 上运行 以连接到 GitLab 6 0 存储库 在 Linux 机器上 从我的本地 Windows 盒子中 我可以使用 SSH URL 来克隆我的 GitLab 服
  • 将参数传递给另一个可变参数函数

    有没有什么方法可以让这段代码按预期编译和工作 而无需求助于va list stuff include
  • Android LVL(许可服务)非常慢! ——解决方案?异步?

    我在网上查了一下 看到其他一些帖子抱怨 Android 许可 LVL 库如何缓慢 但没有解决方案 在 HTC Thunderbolt 全新手机 上 它会使测试应用程序的启动时间延迟 3 5 秒以上 有人对异步调用这个库有任何经验或想法吗 其
  • 如何让 Eclipse 自动生成新 Java 类的 main 方法?

    有谁知道我的 Eclipse 不预加载的原因 public static void main String args 当我创建一个新课程时 我该怎么做才能让它自动出现 Type main and press ctrl space The e
  • 提取 Windows 中任何文件的缩略图

    从任何文件 而不仅仅是不同大小的图像 中提取缩略图的最有效方法是什么 我已经查看了所有内容 其中最有希望的是 Windows API ShellFile 但它似乎没有正确安装 我使用的是Windows 7 不久前 我编写了一个 Thumbn
  • 这些 Linux 内核 Oops 字段的含义是什么?

    我在开发人员的生活中已经遇到过一些 Oops 虽然我熟悉可以从这些 Oops 中检索到的一些信息 但仍然有一些信息我无法理解 因此无法用来解决问题 下面您将找到一个 Oops 示例 我将描述我可以从中推断出什么 然后 我会问剩下的信息可以告
  • Django在syncdb时以自定义方式初始化数据库

    我在开发过程中使用 Django 令人烦恼的是 每次我对模型进行一点更改时 我都需要删除数据库并运行syncdb 为了测试的目的 我想每次运行syncdb时自动将一些初始数据添加到数据库中 我尝试将这些代码放入一个应用程序中 init py
  • bash:如何在没有 date -d 选项的情况下比较 Solaris 上的两个日期

    我试图将日志文件行中输入的日期与昨天的日期进行比较 如果差异超过一天 则它会打印日志文件中的该行 日志档案 more ActiveX2Alarms log 2016 09 30 01 40 14 MET faultManager netwo
  • 为什么我可以在私有类型上使用 auto?

    我对以下代码的编译和运行感到惊讶 vc2012 gcc4 7 2 class Foo struct Bar int i public Bar Baz return Bar int main Foo f Foo Bar b f Baz err
  • 如何将 Excel 配色方案从一个工作簿复制到另一个工作簿

    有时 当我从一个工作簿复制并粘贴到另一个工作簿时 目标配色方案看起来很奇怪 如何将配色方案从一个工作簿复制到另一个工作簿 打开 VBA 并键入以下内容 根据需要更改工作簿的名称 workbooks DestinationWorkbook x
  • 获取手机中安装的所有社交媒体应用程序的列表?

    我正在开发一个应用程序 其中列出了用户移动设备中安装的所有应用程序 我检索了所有应用程序并将其列出在回收视图 现在我想将社交媒体应用程序从该列表中分离出来以用于其他目的 有什么办法可以分离社交媒体应用程序吗 我使用下面的代码从手机检索所有应
  • 何时使用 代替

    正如问题所示 如果我想在 HTML 中添加一些文本 那么我应该何时使用 p 我什么时候应该使用 span 您应该记住 HTML 旨在描述它包含的内容 所以 如果你想传达一段话 那就这么做吧 不过 您的比较并不完全正确 更直接的比较是 何时使
  • 有没有办法用带参数的sql脚本运行impala shell?

    有没有办法使用带参数的 SQL 脚本运行 impala shell 例如 impala shell f home john sql load sql dir1 dir2 dir3 data file 我收到错误 错误 无法解析参数 f ho
  • 流浪者警告:连接被拒绝。重试

    测试默认示例 vagrant init hashicorp precise32 vagrant up 我的盒子 视窗8 1 虚拟盒 5 0 2 流浪者1 7 4 Intel i7 4700MQ CPU 似乎具有 Intel 虚拟化技术 VT
  • 无法分配给引用或变量中的 Angular 产品构建错误

    我无法构建我的角度应用程序的产品版本 IDE 控制台中只有此消息 错误无法分配给引用或变量 所以我只有添加这些选项才能构建 aot false buildOptimizer false 但是 即使使用这些选项 应用程序在部署后也会失败 并在
  • 如何直接使用适配器从 AutoCompleteTextView 中删除数据

    I have AutoCompleteTextView which uses to search the value from database On Click of filtered value it s set to the Auto
  • Angular2 中 valueChanges 的空订阅

    我有一个奇怪的情况 如果留空 订阅永远不会触发 这不起作用 this formGroup get unitCount valueChanges do value gt console log value subscribe 当这工作正常时
  • 如何调用无状态小部件的重建?

    Context 我有两个无状态小部件 页面 HomePage and DetailsPage 显然应用程序启动并启动HomePage 用户可以按下一个按钮来导航到DetailsPage with a Navigator pop 按钮导航回到