我有一个Stateful小部件,只有一个变量count. 每次我按下一个按钮,计数就会递增并显示在屏幕上. 我知道我必须调用setState()才能用新值更新UI. 通常情况下,该操作如下所示:

ElevatedButton(
  onPressed: () {
     setState(() {
        count++;
     });
   }

我的问题是,为什么要在setState()内部递增变量count? 即使我在外面做,它也能很好地工作:

ElevatedButton(
  onPressed: () {
    count++;
    setState(() {});
   }

那么,为什么不用一个更简单的方法,比如updateUI(),而不是setState()呢?Ffltter在内部仍然可以随时调用setState(),但对外部世界来说,它可以公开一个更优雅的API:

ElevatedButton(
    onPressed: (){
      count++;
      updateUI();
    }

当屏幕需要重新绘制时,可以从任何地方调用updateUI().setState()更令人费解,因为它以函数作为参数.目前还不清楚该函数内部应该做些什么. setState()内允许/不允许什么类型的操作?我想知道这里面有什么设计思想. 就这一点而言,Stateless小部件也可以有内部变量.那么为什么它不能有一个updateUI()的方法呢?这仅仅是出于效率的原因吗?

推荐答案

正如您已经正确地指出的那样,Fwing框架的setState方法实质上是在被调用时调度小部件的重新构建.对setState使用匿名函数的主要原因是确保框架知道您打算何时更新小部件的状态.以下是需要理解的一些关键点:

  1. Scheduling a Rebuild:当你呼叫setState时,它会告诉Ffltter计划重新构建窗口小部件.这是必要的,因为Ffltter是声明性的,并且您正在描述基于当前状态的UI应该是什么样子.当状态更改时,您需要通知Ffltter使用更新后的状态重新渲染小部件.

  2. Updating State:setState内部的匿名函数是一个约定,有助于明确您的意图.虽然您确实可以在调用setState之前直接更新状态,但将更新包括在回调中被认为是最佳实践.这是因为它使您的代码更具可读性,并在状态更改和重新生成请求之间保持了清晰的连接.

  3. Conventions and Clarity:使用带有setState的匿名函数已成为Flutter 翼社区的惯例.这是向其他开发人员(以及您future 的自己)发出信号的一种方式,表明您有意更改状态并触发重新构建.它增强了代码的清晰度,使其他人更容易理解您的代码.

  4. Historical Reasons:正如本文提到的https://iiro.dev/set-state/个,这个约定是从Ffltter团队进行的UX研究中产生的.他们发现,与直接的markNeedsBuild方法相比,开发人员更容易理解和正确使用带有匿名回调的setState,但also using the rebuild function a lot less with setState.

总之,虽然在技术上可以在setState中的匿名函数之外更新状态,但遵循在回调中更新状态的约定被认为是最佳实践.这种约定增强了代码的可读性,保持了您的意图的清晰度,并与Ffltter的工作方式保持一致.这是一种使Flutter 开发更直观、更不容易出错的约定.

关于你关于updateUI()方法的 idea :

虽然在技术上可以在不使用setState()的情况下创建一个updateUI()方法来更新用户界面,但基于上述原因,这违背了Ffltter的设计原则.使用setState()是我们推荐的、惯用的方式来处理Flutter 中的用户界面更新.通过遵循此模式,您可以确保采用清晰且一致的方法来管理整个应用程序中的UI状态.

至于无状态窗口小部件:

无状态小部件是为用户界面不随时间变化而基于内部状态而改变的情况而设计的.它们应该是纯粹的和无国籍的,这意味着它们一旦建成,就不会改变.向无状态小部件添加updateUI()方法将与这一设计理念相矛盾.

Helpful Link: 100

Flutter相关问答推荐

本机调试符号包含无效的目录调试符号.目前仅支持Android ABI

Flex ListView用于可滚动和响应的页面

从.gitignore中排除.fvm/fvm_config.json

无法将新文物与Flutter 项目集成在一起

使用Ffltter CREATE创建项目时,androidManifest.xml中缺少包属性

Flutter飞溅屏幕即使在修改后仍显示默认徽标和背景色

Flutter 中的 setState() 内部是如何工作的?

无状态和有状态小部件,我可以同时使用吗?

网页浏览器不支持鼠标滚动的行项目

Flutter列顶部和底部出现不必要的边距问题

我的第一个 flutter 项目出错,启动时为空值?

Flutter:为什么我的 listTile colored颜色 被容器 colored颜色 覆盖了?

如何在两个不同的路由(屏幕)之间正确设置 BlocProvider?

如何在 flutter 中同时使用 ButtonStyle() 和 ElevatedButton.styleFrom() ?

如何从 showModalBottomSheet 中的 topRight 和 topLeft 移除平边

Flutter/Dart 返回_Future的实例而不是实际的字符串值

Flutter 中出现错误空判断运算符用于空值

在 Flutter 中,如何使用文本字段和方形图像进行行布局

如何在 Flutter 中创建类似箭头标签的设计

如何验证位于 PageView 内不同页面的 TextFormFields