1

我有一个使用 ListView.builder 显示的项目列表(5-6 项) 。每个项目都包含一个 DropdownButton 小部件,供用户从 1 到 1000 中选择一个数字,因此包含1000 个 DropdownMenuItems

我实现它如下所示,但问题是向下滚动 ListView太慢而且卡顿。即使 listView 有 5 或 6 个项目,但请注意,每个项目都有一个嵌入的 DropdownButton,其中包含 1000 个 DropdownMenuItem。

有解决办法吗?或者另一种方式来满足我的要求?

注意:即使我将DropdownMenuItems 的数量减少到 100 ,向下滚动 ListView 时它仍然会卡顿。

class List extends StatelessWidget {
   final List<Item> // Contains 5 items.
   final List<int> quantityList = List<int>.generate(1000, (int i) => i);
 //--
   child: ListView.builder(
                  itemBuilder: (buildContext, i) {
                    return MyItem(
                      quantityList,
                    );
                  },
                  itemCount: items.length(),
                )

class MyItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: DropdownButton<int>(
          items: quantityList
              .map(
                (int e) =>
                DropdownMenuItem<int>(
                  value: e,
                  child: Text(e.toString()),
                ),
          )
              .toList(),
        ),
      ),
    );
  }

编辑

我将 MyItem 类更改为如下,但仍然存在同样的问题。

尝试使用ListViewListView.custom而不是ListView.builder来提前构建整个列表,而不是根据这个懒惰地构建整个列表,但仍然是同样的问题。

我还尝试使用--profile配置运行应用程序来模拟发布版本。性能更好,但仍然遭受可怕的口吃和滞后。在模拟器和物理设备上测试。

 class MyItem extends StatelessWidget {
      List<DropDownMenuItem> quantityList; // contains 1k 
      @override
      Widget build(BuildContext context) {
        return Container(
            width:300,
            height:300,
            child: DropdownButton<int>(
              items: quantityList, 
            ),
          ),
        );
      }
4

2 回答 2

2

ListView 将在小部件进出视图时创建和销毁它们。您的 MyItem 小部件是一个非常重的小部件(需要创建和销毁很多东西)。

您可能不希望每个MyItem都成为Scaffold(). 通常,您只有 1 个 Scaffold() 可见,因为它是应用程序的精美根视图。它有一个应用程序栏、小吃店、抽屉等。尝试仅将您Container(...)当前所在的位置body:作为您的MyItem.build().

items:DropdownButton 中,您可以在 DropdownButton 滚动进出视图时构建和销毁项目列表。如果此列表对于列表中的每个小部件都相同,就像上面的测试代码一样,请创建一个List<Widget>[]包含 DropdownMenuItem 小部件并将其传递给MyItem()小部件的列表。就像是:

//In your widget with the ListView
List<Widget> myItems;

//In the initState() of your widget with the ListView
...
myItems = quantitySelection.map(
   (int e) => DropdownMenuItem<int>(
      value: e,
      child: Text(e.toString()),
    ),
).toList(),
...


//In your ListView.builder()
return MyItem(
  ...  
  items: myItems,
  ...
);

//In your MyItem.build() ->  DropdownButton()
...
DropDownButton(
   items: items
),
...

FWIW - 我们有一个包含复杂子项的 ListView,我们用 10,000 个项目进行测试。Flutter 中的调试版本和发布版本之间的性能存在显着差异。它在调试版本中有点卡顿,但在发布版本中非常流畅。

于 2021-09-19T15:16:03.010 回答
0

我能够通过仅使用 的cacheExtent属性ListView.builder,将其设置为来解决问题list.length*200。这是一种解决方法,知道在我的情况下列表长度总是很小。

预先构建 DropDownMenuItems 并没有让用户感知到性能增强,但无论如何这是一个很好的推荐做法,而不是为每个列表项一遍又一遍地构建相同的 DropDownMenuItems。

尽管根据文档:ListView 和 ListView.separated 并没有延迟加载项目,而是在开始时将它们全部构建起来,但我在滚动过程中一直遇到与 ListView.builder 相同的卡顿和滞后。

于 2021-09-21T16:05:05.460 回答