简体   繁体   English

可以在 Flutter 的后续构建中重用小部件吗?

[英]Is it ok to reuse widgets on subsequent build in Flutter?

I've been searching around and didn't quite find a suitable answer to this question: is it ok to reuse a widget in a subsequent build call?我一直在四处寻找,并没有找到这个问题的合适答案:可以在随后的构建调用中重用小部件吗? By that I mean that I create a StatefulWidget and in the build function I keep an internal reference to the returned widget.我的意思是我创建了一个StatefulWidget并且在构建函数中我保留了对返回的小部件的内部引用。 On later build (if I determine that nothing has changed since last build), I then return the last widget instead of building a new one.在以后的构建中(如果我确定自上次构建以来没有任何变化),然后我返回最后一个小部件而不是构建一个新的小部件。

I understand that one should avoid that, create simple builds and optimise invalidation process so that complex widgets don't get rebuilt too often.我知道应该避免这种情况,创建简单的构建并优化失效过程,这样复杂的小部件就不会经常重建。 But under some circumstances, I find this can be a good solution.但在某些情况下,我发现这可能是一个很好的解决方案。

Reading on this official doc page in particular, it is stated:特别是在这个官方文档页面上阅读,它指出:

The traversal to rebuild all descendents stops when the same instance of the child widget as the previous frame is re-encountered.当再次遇到与前一帧相同的子小部件实例时,重建所有后代的遍历将停止。 This technique is heavily used inside the framework for optimizing animations where the animation doesn't affect the child subtree.这种技术在框架内被大量使用,用于优化动画不影响子树的动画。 See the TransitionBuilder pattern and the source code for SlideTransition, which uses this principle to avoid rebuilding its descendents when animating.请参阅 TransitionBuilder 模式和 SlideTransition 的源代码,它使用此原则来避免在动画时重建其后代。

So doing something like this should be acceptable:所以做这样的事情应该是可以接受的:

abstract class SmartState<T extends StatefulWidget> extends State<T> {
  Widget _lastBuild;
  T _previousWidget;

  bool shouldRebuild(T previousWidget);
  Widget doBuild(BuildContext context);

  @override
  @mustCallSuper
  Widget build(BuildContext context) {
    final T previousWidget = _previousWidget;
    _previousWidget = widget;

    if (previousWidget != null && _lastBuild != null && !shouldRebuild(previousWidget)) {
      return _lastBuild;
    }

    _lastBuild = doBuild(context);
    return _lastBuild;
  }
}

As a little background, I intend to extend this class in a list item.作为一个小背景,我打算在列表项中扩展这个类。 The list itself changes at times and is rebuilt with the new items, although most of the items remain the same, I just rearrange them, remove or add some.列表本身有时会更改并使用新项目重建,尽管大多数项目保持不变,我只是重新排列它们,删除或添加一些。 Also note that I had to put them in a Wrap widget because of design requirements.另请注意,由于设计要求,我不得不将它们放在Wrap小部件中。

So does anyone has any counter-indication or better solution than this.是否有人有任何相反的迹象或比这更好的解决方案。 And most of all, I would like to know if it is considered ok or good practice to do such a reuse.最重要的是,我想知道进行这样的重用是否被认为是好的或好的做法。 Thanks!谢谢!

You are unnecessary fighting with the framework, flutter internally takes care of rebuild by using methods like canUpdate() method.你没有必要和框架打架,flutter 内部会使用 canUpdate() 等方法来处理重建。 https://api.flutter.dev/flutter/widgets/Widget/canUpdate.html . https://api.flutter.dev/flutter/widgets/Widget/canUpdate.html

And for your solution to reduce build method calls.并为您减少构建方法调用的解决方案。 You are actually overcomplicating your widget instantiation.您实际上使小部件实例化过于复杂。 with no performance uplift, I would say even maybe worse performance(Please don't mind).如果没有性能提升,我会说性能甚至可能更差(请不要介意)。 As you are always throwing a new object to your SmartState class whenever a build is called until and unless those widgets have a const constructor(which helps for runtime final object) or you can see from the above link that widgets are compared on two basis keys and runtime type, Though I would say constConstructor would be more performing but dart and other languages have more support for objects rather than const variables.因为每当调用构建时,您总是向 SmartState 类抛出一个新对象,除非这些小部件具有 const 构造函数(这有助于运行时最终对象),或者您可以从上面的链接中看到,小部件在两个基础键上进行比较和运行时类型,虽然我会说 constConstructor 的性能会更好,但 dart 和其他语言对对象而不是 const 变量有更多支持。 Most of the object disposal task is taken care by dart() itself.大多数对象处理任务由 dart() 本身处理。

So to finalize my answer you can do this and this may clear your doubt.因此,要完成我的答案,您可以这样做,这可能会消除您的疑虑。 Do this in any stateful widget and you may find your answer在任何有状态小部件中执行此操作,您可能会找到答案

  void initState() { 
    super.initState();
  print( SizedBox() == SizedBox());  //OutPut: false 
  }

A quick solution is to create a class like this.一个快速的解决方案是创建一个这样的类。

class WidgetConstant {
  static const SizedBox _sizedBox = SizedBox(
    height: 2,
  );

  WidgetConstant._();
  static Widget sizedBox() => _sizedBox;
}

And now compare using the code below现在使用下面的代码进行比较

void initState() { 
    super.initState();
  print( WidgetConstant.sizedBox() == WidgetConstant.sizedBox(););  //OutPut: true 
}

Conclusion: flutter is already optimized so enjoy using this highly performing framework 😃.结论:flutter 已经被优化,所以享受使用这个高性能框架😃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM