原文地址:flutteragency.com/what-is-the…
原文作者:flutteragency.com/author/john…
发布时间:2021年8月18日 - 6分钟阅读
Flutter提供了一组内置的小部件,以将不同的效果应用于移动应用程序。因此,在这篇文章中,我们将看到函数和类之间的区别是什么,以创建可重用的小部件。
让我们开始吧。
创建可重复使用的小部件的函数和类之间的区别是什么?
重要的区别。
它主要用于公共小部件,可以被重复使用。只使用一次的私有函数并不重要。尽管了解这种行为是很好的。
使用函数而不是类,有一个重要的区别。那就是,框架不知道函数,但可以看到类。
考虑一下下面的 "widget "函数。
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,
);
}
}
像这样使用。
ClassWidget(
child: new ClassWidget(),
);
在函数的情况下,生成的widget树看起来像这样。
Container
Container
而对于类,widget树是这样的。
ClassWidget
Container
ClassWidget
Container
这很重要,因为它改变了框架在更新widget时的行为方式。
为什么这很重要?
通过使用函数将你的widget树分割成多个widget,你会将自己暴露在bug中,并错过一些性能优化的机会。
不能保证你通过使用函数会有bug。但是通过使用类,你可以确保你不会遇到这些问题。
这里有一些Dartpad上的交互式例子,你可以自己运行,以更好地理解这些问题。
-
dartpad.dev/1870e726d7e… 这个例子展示了通过将你的应用程序分割成函数,你可能会不小心破坏像AnimatedSwitcher这样的东西。
-
dartpad.dev/a869b21a2eb… 这个例子展示了类是如何允许更精细地重建widget树,提高性能的。
-
dartpad.dev/06842ae9e4b… 这个例子展示了通过使用函数,在使用Inherited widget(如Theme或provider)时,你会暴露出误用BuildContext和面临bug。
下面是一个关于使用函数和类的区别的精选列表。
- 类。
- 允许性能优化 constructor,更细化的重建
- 确保在两个不同的布局之间切换时能正确地处理资源(函数可能会重复使用一些以前的状态)。
- 确保热重载工作正常,使用函数可以破坏showDialogs和类似的热重载。
- 被整合到小部件检查器中
- 我们在devtool显示的widget树中看到ClassWidget,这有助于理解屏幕上的内容。
- 我们可以覆盖debugFillProperties来打印传递给widget的参数是什么。
更好的错误信息。
- 如果发生像ProviderNotFound这样的异常,框架会给你当前构建的widget的名字。
- 如果你只在函数+生成器中分割了你的widget树,你的错误就不会有一个有用的名字。
- 可以定义键
- 可以使用上下文API
- 函数。
- 有较少的代码,可以使用代码生成的functional_widget来解决
对于Flutter框架
Dart同时支持程序化和OOP。但是,flutter框架完全是通过使用类(op)来构建的。因为一个大型的可管理的框架不能使用过程式创建。
- 这里创建一个列表,说明他们使用类而不是函数来制作小部件的原因。
- 大多数时候,build方法(子部件)会调用大量的同步和异步函数。
- 所以build()方法需要保留在单独的类widget中。因为所有被build()方法调用的其他方法都可以保留在一个类中。
- 使用widget类,你可以创建许多其他的类,而不需要重复写同样的代码。
- 同时,使用继承(extend)和多态(override),你可以创建你自己的自定义类。
在下面的例子中,让我们通过扩展MaterialPageRoute来定制(Override)动画(因为它是我们要定制的默认过渡)。
class MyCustomRoute<T> extends MaterialPageRoute<T> {
MyCustomRoute({ WidgetBuilder builder, RouteSettings settings })
: super(builder: builder, settings: settings);
@override //Customize transition
Widget buildTransitions(BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
if (settings.isInitialRoute)
return child;
// Fades between routes. (If you don't want any animation,
// just return child.)
return new FadeTransition(opacity: animation, child: child);
}
}
函数不能为其参数添加条件。但是使用类部件的构造函数,你可以像下面这样做。
const Scaffold({
Key key,
this.bottomNavigationBar,
this.bottomSheet,
this.backgroundColor,
this.resizeToAvoidBottomPadding,
this.resizeToAvoidBottomInset,
this.primary = true,
this.drawerDragStartBehavior = DragStartBehavior.start,
this.extendBody = false,
this.extendBodyBehindAppBar = false,
this.drawerScrimColor,
this.drawerEdgeDragWidth,
}) : assert(primary != null),
assert(extendBody != null),
assert(extendBodyBehindAppBar != null),
assert(drawerDragStartBehavior != null),
super(key: key);
函数不能使用const。类Widget可以在它们的构造函数中使用const(会影响主线程的性能)。
你可以使用同一个类/对象的实例创建任意数量的独立widget。但函数不能创建独立的widget实例,但重复使用可以。
结语。
感谢你和我们一起走过Flutter之旅!!!继续学习
继续学习 !!! 继续Fluttering !!!!
Flutter Agency 是我们专门为 Flutter 技术和 Flutter 开发人员提供的门户平台。该门户网站充满了来自Flutter的酷炫资源,如Flutter Widget指南、Flutter项目、代码库等。
Flutter Agency 是致力于 Flutter 技术的最受欢迎的在线门户之一。每天有数以千计的独特访问者来到这个门户网站,以提高他们对Flutter的认识。