setState Dart/Flutter 中带有花括号的胖箭头符号

Posted

技术标签:

【中文标题】setState Dart/Flutter 中带有花括号的胖箭头符号【英文标题】:Fat Arrow notation with curly braces in setState 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 lambda/shortland function confusion的可能重复 这不是重复的,这是一个非常有趣的问题@MazinIbrahim。这是Dart 2.2 中引入的定义Set 的新方法的结果。 【参考方案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; ,除非您想要返回一个集合或地图。

【讨论】:

嗨,谢谢。是的,我知道推荐的方法就是您所建议的。当我在玩代码并且我认为不起作用的东西时,这个问题出现了。

以上是关于setState Dart/Flutter 中带有花括号的胖箭头符号的主要内容,如果未能解决你的问题,请参考以下文章

Dart // Flutter:如何根据条目的内容从列表中删除项目

在 Dart / Flutter 中解析嵌套的 XML

是否可以用Dart / Flutter绘制图像?

错误 Dart/Flutter: 'context != null': 不正确

异步/等待/然后在 Dart/Flutter 中

如何删除 List<MyDataModel> 的重复项(Dart/Flutter)