在关于这个问题的讨论上,2 年前 StackOverflow 有一个经典的回答:使用函数和使用类来构建可复用得组件有什么区别?,大家可以去看看。其中提到得一个关键因素是 Flutter 框架能够检测组件树的类对象,从而提高复用性。而对于私有的方法来说 Flutter 在更新的时候并不知道该如何处理。
答主也对比了使用类和函数的优劣势。使用类构建的方式:
.支持性能优化,比如使用 const 构造方法,更细颗粒度的刷新;class _MyStatefulWidgetState extends State<MyStatefulWidget> { int _counter = 0; @override Widget build(BuildContext context) { return Row( children: [ Text('Counter: $_counter'), Container( child: Column( children: [ Text('Hello'), Row( children: [ Text('there'), Text('world!'), ], ), ], ), ), ], ); } }括号有点多,对吧,一眼看过去都懵圈了 —— 这也是很多初次接触 Flutter 的人吐槽地方,可以说让不少人直接放弃了! 最直接的方式就是将部分代码抽离成为一个私有方法,比如像下面这样。
class _MyStatefulWidgetState extends State<MyStatefulWidget> { int _counter = 0; // 堆代码 www.duidaima.com Widget _buildNonsenseWidget() { return Container( child: Column( children: [ Text('Hello'), Row( children: [ Text('there'), Text('world!'), ], ), ], ), ); } @override Widget build(BuildContext context) { return Row( children: [ Text('Counter: $_counter'), _buildNonsenseWidget(), ], ); } }将深度嵌套的组件代码单独抽成了一个返回 Widget 的私有方法,看起来确实让代码简洁不少。那么问题就解决了吗?我们来看一下当状态改变的时候会发生什么。我们知道,当状态变量_counter 改变后,Flutter 会调用 build 方法刷新组件。这会导致 _buildNonsenseWidget 这个方法在刷新的时候每次都会被调用,意味着每次都会创建新的组件来替换旧的组件,即便两个组件没有任何改变。而事实上,我们应该只重建那些变化的组件,从而提高性能。现在再来看使用类组件的方式,实际上有代码模板的情况下,编写一个 StatelessWidget 非常简单。使用类组件后的代码如下所示。代码确实会比函数的方式多,但是实际上大部分不需要我们手敲。
class _MyStatefulWidgetState extends State<MyStatefulWidget> { int _counter = 0; @override Widget build(BuildContext context) { return Row( children: [ Text('Counter: $_counter'), // The deeply nesting widget is now refactored into a // stateless const widget. No more needless rebuilding! const _NonsenseWidget(), ], ); } } class _NonsenseWidget extends StatelessWidget { const _NonsenseWidget(); @override Widget build(BuildContext context) { return Container( child: Column( children: [ Text('Hello'), Row( children: [ Text('there'), Text('world!'), ], ), ], ), ); } }这里注意,以为这个_NonsenseWidget 在组件得声明周期不会改变,因此使用了 const 的构造方法。这样在刷新过程中,就不会重新构建了!