简体   繁体   English

Flutter 扩展列表优化、性能和最佳实践

[英]Flutter Expanding List Optimisation, Performance and Best Practices

What is the best practice for displaying a list of Widgets in flutter, where the list can be extended or reduced in length via State.在 flutter 中显示小部件列表的最佳做法是什么,其中可以通过 State 扩展或减少列表的长度。

Let's say we have a Provider State that determines the length and we render widgets accordingly.假设我们有一个 Provider State 来确定长度并相应地呈现小部件。

List _state = Provider.of<Somesuch>(context).routes;

for(int i = 0; i < _state.length; i ++)
Container(child: Text('Item $I'),

The problem on testing this is that if the state length increases, all child widgets seem to be rebuilt.测试这个的问题是,如果 state 长度增加,所有的子部件似乎都被重建了。 Due to the number of animations contained in each actual child, this does not seem to be an optimal approach.由于每个实际孩子中包含的动画数量,这似乎不是最佳方法。

We have experimenting with nesting the children:我们尝试嵌套孩子:

class NestContainer extends StatelessWidget {
  NestContainer({
   this.child = const SizedBox(),
   this.nextChild = const SizedBox(),
});
final Widget child, nextChild;
}

Widget build(BuildContext context) {
  return Stack(children:[
    child,
    nextChild,
  ]);
}

then as the child of some Widget:然后作为一些 Widget 的孩子:

Builder(builder: (context) {
  List _state = Provider.of<Somesuch>(context).routes;

  buildContainer(int index){
    return NestContainer(
      child: Container(child: Text('Item $index')),
      nextChild

: _state.asMap().containsKey(index + 1) ?
    buildContainer(index + 1) : const SizedBox()
    
    }
return buildContainer(0);
});

This seems to not cause the rebuilds but I am concerned about the use of functions as this is discouraged in the docs.这似乎不会导致重建,但我担心函数的使用,因为文档中不鼓励这样做。

Also it makes passing actual content to these children for more involved as technically all potential children (that are actually page routes contained in a Map).它还使得将实际内容传递给这些孩子,以便在技术上更多地涉及所有潜在的孩子(实际上是地图中包含的页面路由)。 Each NestContainer would need to receive the whole Map so that it can render the correct item from it which means passing a lot of unused data to every single NestContainer.每个 NestContainer 都需要接收整个 Map 以便它可以从中呈现正确的项目,这意味着将大量未使用的数据传递给每个 NestContainer。

What is the best approach for dealing with this matter?处理这个问题的最佳方法是什么?

Keys are important.钥匙很重要。 They allow flutter to look at a stack of widgets as a whole and determine whether anything inside that stack has changed.它们允许 flutter 将一堆小部件作为一个整体来查看,并确定该堆栈中的任何内容是否发生了变化。

List _state = Provider.of<Somesuch>(context).routes;

for(int i = 0; i < _state.length; i ++)
Container(key: ValueKey('Container $I'), child: Text('Item $I'),

The addition of that key means that if that container does not change and it's place in the list does not change none of it will be checked for a change.添加该键意味着如果该容器没有更改并且它在列表中的位置没有更改,则不会检查任何更改。

However, this is not the full answer.但是,这不是完整的答案。 Memory usage is based around a number of rendered widgets on screen among other things. Memory 的使用基于屏幕上呈现的一些小部件等。 Getting rid of anything not on screen is important.摆脱屏幕上没有的任何东西很重要。

Many will say that the best way is to remove unused widgets from the tree.许多人会说最好的方法是从树中删除未使用的小部件。 ie IE

Stack(children:[
someStatefield ? SomeWidget() : SizedBox()
])

This is true but it is not always possible particularly in a complex navigator.这是事实,但并不总是可行,尤其是在复杂的导航器中。 The idea is instead to replace widgets that can't be seen on screen with the minus amount of content possible until they are needed to be seen again.这个想法是用尽可能少的内容替换屏幕上看不到的小部件,直到需要再次看到它们为止。

The easiest way is to use the Visibility class. With Visibility(visible: false) , the child of this class will be replaced with a SizedBox and it's content restored when set to true.最简单的方法是使用 Visibility class。使用Visibility(visible: false)时,此 class 的子级将被替换为 SizedBox,并且在设置为 true 时恢复其内容。 Adding maintainState: true will allow it to maintain responses to any other state changes without rendering any content or performing any anumations until it's visible again.添加maintainState: true将允许它保持对任何其他 state 更改的响应,而无需呈现任何内容或执行任何动画,直到它再次可见。

Visibility(
  visible: (true or false based on your state),
  maintainState: true // ensures the child still responds to changes in state despite rendering no content or animations
  child: // Your Widgets and content that will be replaced by a SizedBox when not visible
)

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

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