【问题标题】:Fat Arrow notation with curly braces in setState Dart/FluttersetState Dart/Flutter 中带有花括号的胖箭头符号
【发布时间】:2019-08-16 11:06:30
【问题描述】:

我对 Dart/Flutter 非常陌生,我对 => 表示法感到困惑。文档说 => 表示法用作返回单个表达式的简写。

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

当我尝试在颤振应用程序中设置状态时,我的疑问就出现了。

RaisedButton(
  onPressed: () => {
    setState(() {
      print('hello');
      _products.add('More stuff');
    })
  },
  child: Text('Add Product'),
),

现在,当我用 => 表示法更改 setState 方法时

RaisedButton(
  onPressed: () => {
    setState(() => {
      print('hello'),
      _products.add('More stuff'),
    })
  },
  child: Text('Add Product'),
),

上述两种方法都有效,即它们按预期设置状态。我所要做的就是在使用粗箭头符号时将分号更改为逗号。

这背后的逻辑是什么?粗箭头符号如何与包含多个表达式的花括号一起使用。

编辑

正如 Hemanth Raj 所说,=> 返回一个集合,包含 => 符号的代码段可以编写如下。

RaisedButton(
  onPressed: () => {
    setState(() {
     return {
       print('hello'),
       _products.add('More stuff'),
     };
    })
  },
  child: Text('Add Product'),
),

返回的set 包含打印函数和_products.add 如何实际更新状态。它不应该抛出某种错误吗,因为通常 setState 是由诸如_products.add('More stuff'); 之类的表达式完成的。

【问题讨论】:

标签: dart flutter


【解决方案1】:

这是我很想回答的有趣问题之一。

正如官方文档所说的here,是的,=> 用作{ return ... } 的简写语法,这意味着=> 将只返回右侧产生的任何内容。

同样来自Dart 2.2 及以上,Set 可以定义为用逗号分隔的值括在{} 中,如文档here 中所述。

因此,您正在使用的语法,即 {} 与用逗号分隔的语句,它被 => 函数视为 Set。每个元素都是一个函数调用,() => { f(a) , f(b), g(a),} 将返回一个 Set,其中包含每个函数调用返回的元素。

此示例可能会帮助您了解幕后发生的事情:

dynamic reflect(dynamic a){
  return a;
}

void main() {  
    Function shortHand = () => {reflect(1),reflect('a'),reflect({}),reflect([]),}; // this function when called will return a Set<dynamic>
    print(shortHand().runtimeType); // will print `_LinkedHashSet<dynamic>`
}

所以语法

() =&gt; '...' 返回一个String

() =&gt; [ ... , ..., ...] 返回一个List

同样() =&gt; { ... , ... , ... }实际上返回一个Set

注意:不建议使用这种以逗号分隔的函数调用返回集合的方法,除非您希望将 Set 作为结果返回,否则请不要使用它


回复编辑:

让我为您分解函数调用和结果。所以你的代码是这样的,

() => {
    setState(() {
     return {
       print('hello'),
       _products.add('More stuff'),
     };
    })
  }

这里=&gt; 返回一个Set,结果为setState,即它会返回{ (result of setState call) },它可能是{ null }

当您调用setState 时,下面的代码将被执行,它再次返回带有{ (result of print), (result of _product.add), }Set

() {
      return {
        print('hello'),
        _products.add('More stuff'),
      };
    }

当您执行_products.add('More stuff') 时,状态将更新,其中'More stuff' 将被添加到_products,无论您在哪里调用它。当 setState 被调用时,小部件将使用 _products 重新构建并添加新数据。

希望这有帮助!

【讨论】:

  • 感谢您的回答,请检查我在问题中所做的修改。
  • 感谢您的更新。我仍然对如何在 return 语句中设置小部件状态感到困惑。是不是因为在 return 语句中运行的所有函数和表达式最终都会影响到小部件的状态?
  • Yes 状态将更新,因为您正在执行 _products.add('More stuff') ,其中 'More stuff' 将被添加到 _products 中,无论您在哪里调用它。
  • 也明白了,setState 被调用了,小部件将被重建,_products 将添加新数据。
【解决方案2】:

为了记录,您正在做的推荐语法是:

RaisedButton(
    onPressed: () {
      setState(() {
        print('hello');
        _products.add('More stuff');
      });
    },
    child: Text('Add Product'),
),

(args) =&gt; { statements } 的语法 不是 Dart 编写函数体的方式,你可以使用 (args) { statements }(args) =&gt; singleExpression

另外,您需要用分号 ; 而不是逗号来终止语句。

正如其他人所指出的,您使用(args) =&gt; { print("something"), somethingElse } 的语法实际上是创建一个集合(Set&lt;void&gt;,因为print 的返回类型是void)并返回它。

这是一场小语法错误的完美风暴,这对 JavaScript 程序员来说似乎是合理的,但实际上这些错误在 Dart 中意味着完全不同的东西。 而且,更糟糕的是,代码有效。集合字面量将按顺序评估其表达式,并且无论如何都没有人看到创建的集合。语法只是没有概括——你不能将任何表达式更改为,比如说,一个 for 循环(但是,你将能够在下一个版本的 Dart 中)。

因此,在 Dart 中,切勿使用 =&gt; {,除非您想要返回一个集合或地图。

【讨论】:

  • 嗨,谢谢。是的,我知道推荐的方法就是您所建议的。当我在玩代码并且我认为不起作用的东西时,这个问题出现了。
猜你喜欢
  • 2017-04-26
  • 2016-05-28
  • 2022-01-19
  • 2017-05-22
  • 2020-06-18
  • 2020-06-21
  • 2019-02-25
  • 2020-03-01
相关资源
最近更新 更多