StatefulWidget的build中声明Widget变量与直接实例化的性能差异?
关于Flutter组件重构写法的性能疑问
之前看到一种Flutter代码写法会因引发不必要的重构建影响性能,具体是在State类中把部分组件抽成类内方法:
class _MyStatefulWidgetState extends State<MyStatefulWidget> { int _counter = 0; 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(), ], ); } }
现在想请教:如果采用下面这种先将组件实例赋值给变量再使用的写法,会不会产生同样的性能问题?还是和直接在children里实例化组件的写法性能一致?
写法一:先赋值给变量
class _MyStatefulWidgetState extends State<MyStatefulWidget> { int _counter = 0; @override Widget build(BuildContext context) { final dummy = DummyWidget(); return Row( children: [ Text('Counter: $_counter'), dummy, ], ); } }
写法二:直接实例化
class _MyStatefulWidgetState extends State<MyStatefulWidget> { int _counter = 0; @override Widget build(BuildContext context) { return Row( children: [ Text('Counter: $_counter'), DummyWidget(), ], ); } }
解答
这两种写法(先赋值变量和直接实例化)的性能表现完全一致,都不会出现那种抽成State类方法的写法带来的性能问题。
原因很明确:
- 抽成State类方法的写法中,每次
build执行时,_buildNonsenseWidget()都会重新生成一套全新的Container、Column、Text等Widget实例。即使这些组件的内容没有任何变化,Flutter的diff算法也会判定它们是新的Widget,从而触发整个子树的重构建。 - 而使用独立Widget类(
DummyWidget)的两种写法,不管是先赋值给变量还是直接写在children里,本质都是创建一个DummyWidget的实例。Flutter的diff算法会对比Widget的类型和key,只要DummyWidget自身的配置(比如传入的参数)没有变化,就不会触发它内部的build方法,只会复用原来的Element和RenderObject,避免不必要的重绘。
简单说,只要是用独立的Widget类来封装组件,不管是直接实例化还是先存变量,性能都是一样的,和那种在State里写_build方法的错误写法有本质区别。
内容的提问来源于stack exchange,提问作者anonymous-dev
相关产品推荐
相关产品推荐

