我已经意识到,可以使用普通函数创建小部件,而不用继承StatelessWidget的子类。一个例子是这样的:
Widget function({ String title, VoidCallback callback }) { return GestureDetector( onTap: callback, child: // some widget ); }
这很有趣,因为它需要 远远 比一个全面的类更少的代码。例:
class SomeWidget extends StatelessWidget { final VoidCallback callback; final String title; const SomeWidget({Key key, this.callback, this.title}) : super(key: key); @override Widget build(BuildContext context) { return GestureDetector( onTap: callback, child: // some widget ); } }
所以我一直在想:创建小部件的函数和类之间在语法上是否有区别?使用函数是否是一种好习惯?
TL; DR:相对于函数,更喜欢使用类来制作 可重用的 小部件树。
编辑 :弥补一些误解:这不是引起问题的函数,而是解决一些问题的类。
如果一个函数可以做同样的事情,Flutter将不会有StatelessWidget。
同样,它主要针对可重用的公共小部件。私有功能只使用一次并不重要,尽管知道这种行为仍然很好。
使用函数而不是使用类之间有一个重要的区别,即:框架不知道函数,但是可以看到类。
考虑以下“窗口小部件”功能:
Widget functionWidget({ Widget child}) { return Container(child: child); }
使用这种方式:
functionWidget( child: functionWidget(), );
它相当于类:
class ClassWidget extends StatelessWidget { final Widget child; const ClassWidget({Key key, this.child}) : super(key: key); @override Widget build(BuildContext context) { return Container( child: child, ); } }
这样使用:
new ClassWidget( child: new ClassWidget(), );
在纸上,两者似乎做的完全一样:创建2 Container,一个嵌套在另一个中。但是实际情况略有不同。
Container
对于函数,生成的窗口小部件树如下所示:
Container Container
在使用类时,小部件树为:
ClassWidget Container ClassWidget Container
这很重要,因为它会更改更新小部件时框架的行为。
通过使用函数将窗口小部件树拆分为多个窗口小部件,您将面临许多错误,并错过了一些性能优化。
不能保证通过使用函数 会 遇到错误,但是通过使用类,可以 保证 不会遇到这些问题。
以下是Dartpad上的一些交互式示例,您可以运行这些示例来更好地理解问题:
https://dartpad.dev/1870e726d7e04699bc8f9d78ba71da35 此示例展示了如何通过将应用拆分为功能来意外破坏诸如AnimatedSwitcher
AnimatedSwitcher
https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1 此示例展示了类如何允许对小部件树进行更细粒度的重建,从而提高了性能
https://dartpad.dev/06842ae9e4b82fad917acb88da108eee 此示例展示了如何通过使用函数使自己暴露于滥用BuildContext并在使用InheritedWidgets(例如Theme或provider)时面临错误。
以下是精选的使用函数和类之间的区别的列表:
类:
允许性能优化(const构造函数,更精细的重建)
showDialogs
ClassWidget
更好的错误消息 如果发生异常(例如ProviderNotFound),框架将为您提供当前正在构建的小部件的名称。如果仅将小部件树拆分为功能+ Builder,则错误将没有有用的名称
Builder
可以定义键
可以使用上下文API
功能:
更少的代码(可以使用生成代码的functional_widget来解决)
总体而言,由于这些原因,在类上使用函数来重用窗口小部件被认为是不好的做法。 您 可以 ,但是将来可能会咬您。