在我的Ffltter应用程序中,我使用的是AnimatedList,有AnimatedList个项目,屏幕上一次只能显示几个项目.

当我第一次运行它时,我可以在日志(log)中看到只构建了必要的项.但如果我刷新列表的内容,出于某种原因,AnimatedList会重新构建每一项,这会让我的应用程序变得滞后.

以下是代码:

class _MyHomePageState extends State<MyHomePage> {

  static const _durationMin = Duration(microseconds: 1);
  final List<String> _items = List.generate(100, (index) => "Item at $index");
  final GlobalKey<AnimatedListState> _listKey = GlobalKey();
  late ScrollController _scrollController;
  
  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController(initialScrollOffset: 0);
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  void _onUpdate() {
    _listKey.currentState?.removeAllItems((_, __) => const SizedBox.shrink(), duration: _durationMin);
    _listKey.currentState?.insertAllItems(0, _items.length, duration: _durationMin);
  }

  Widget _buildItemWidget(String text) {
    return ListTile(
      title: Text(text),
      trailing: IconButton(
        icon: const Icon(Icons.remove),
        onPressed: () {},
      ),
    );
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: SafeArea(
        child: AnimatedList(
          key: _listKey,
          padding: EdgeInsets.zero,
          controller: _scrollController,
          initialItemCount: _items.length,
          itemBuilder: (context, index, animation)
          {
            print("index : $index");
            return _buildItemWidget(_items[index]);
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _onUpdate,
        child: const Icon(Icons.refresh),
      ),
    );
  }
  
}

因此,当我运行这款应用时,我在日志(log)中看到了以下内容:

index : 0
...
index : 18

但如果我按下浮动操作按钮,这是我在日志(log)中看到的:

index : 0
...
index : 99

为什么我会有这样的行为?我如何修复它,以便当我按下浮动操作按钮时,它只重建必要的项?

谢谢你的帮助

推荐答案

如果你看到removeAllItems的文档,它会说:

立即删除项目.但是,这些项仍然会持续出现,在此期间,构建器必须根据需要构建其小部件.

这意味着SizedBox.shrink()小部件将保留为_durationMin,但您在调用insertAllItems之后立即调用insertAllItems,这样构建器将使用SizedBox.shrink()小部件构建所有SizedBox.shrink()个项目.SizedBox.shrink()的高度为0,这意味着它们在屏幕上都是可见的,因此它们都是构建的.

有一些场景你可以try :

  1. 如果您将removeAllItems的持续时间更改为Duration.zero,您可以看到它将按预期工作(项仅在索引18之前构建).这是因为在调用insertAllItems时,所构建的微件是那些具有实际高度的微件ListTile.
  2. 如果将SizedBox.shrink()替换为Text('test'),您将看到构建的小部件数量减少(直到索引99,但在我的例子中直到索引51),因为现在屏幕上可见的小部件更少了.

Note:当我说"在屏幕上可见"时,它还包括最后一个可见项之后的缓冲区项.

Flutter相关问答推荐

Riverpod生成器和生成util类

audioQuery不会等待判断存储权限

遇到图像路径格式问题

ReCAPTCHA Enterprise中的严重安全漏洞

Android Studio将不会构建iOS模拟器应用程序,因为plist.info有问题

Flex ListView用于可滚动和响应的页面

在选项卡栏视图中搜索和筛选不起作用

dotenv:未处理的异常:FileNotFoundError的实例

如何更改Flutter 中文本的混合模式?

构建上下文不能跨异步间隙使用

Flutter http 请求获取 null

找不到任何与 com.google.firebase:firebase-sessions:[15.0.0, 16.0.0) 匹配的版本

添加appBar时绘制的线条发生偏移 Flu

如何在android中 Select 任何文件/文件路径 - Flutter

是否有可能减少代码的编写,例如:ref.read(countProvider.notifier) - 在构建方法中?

如何从底部导航栏打开 bottomModal 表?

如何在 Flutter 中使用 drawLine() 和 drawCircle() 绘制等距离的 4 条线

Flutter中如何连续获取TextField的文本是否为空?

函数中的变量在 Dart 中应该有什么关键字?

我的主屏幕上的 FutureBuilder 不断重新加载(但仅在其他屏幕上时)?