我已经意识到可以使用普通函数而不是继承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 ); } }
所以我一直想知道:除了创建小部件的函数和类之间的语法之外,还有什么区别吗?使用函数是一种好习惯吗?
编辑 :Flutter 团队现在对此事采取了官方立场,并表示课程更可取。见//www.youtube.com/watch?v=IOyq-eTRhvo)
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 此示例展示了如何通过使用函数,在使用 InheritedWidgets(例如主题或提供程序)时将自己暴露于滥用 BuildContext 和面临错误
以下是使用函数和类之间差异的精选列表:
课程:
允许性能优化(const 构造函数,更细粒度的重建)
showDialogs
ClassWidget
更好的错误消息 如果发生异常(如 ProviderNotFound),框架将为您提供当前构建的小部件的名称。如果您仅在函数 + 中拆分小部件树Builder,则您的错误将没有有用的名称
Builder
可以定义键
可以使用上下文 API
职能:
代码更少(可以使用代码生成功能小部件来解决)
总的来说,由于这些原因,使用函数而不是类来重用小部件被认为是一种不好的做法。 你 可以 ,但它可能会在未来咬你。