【问题标题】:How to prevent widget re-render on ListView scroll如何防止小部件在 ListView 滚动上重新渲染
【发布时间】:2019-06-18 04:36:03
【问题描述】:

我正在构建一个包含图片和视频的帖子的时间线。

滚动列表时,图像和帖子本身会不断重新渲染。这会导致应用程序运行缓慢,因为必须重新计算尺寸 + 加载图像(在第二次加载时从本地缓存中加载)。

如何防止整个帖子小部件被重建?

这就是说明的问题。请注意滚动后的加载图标+淡入动画。

Demo of the problem here (GIF)

这是ListView的代码。

  ListView.builder(
      physics: const AlwaysScrollableScrollPhysics(),
      cacheExtent: 30,
      addAutomaticKeepAlives: true,
      padding: const EdgeInsets.all(0),
      itemCount: _posts.length,
      itemBuilder: (context, index) {
        var post = _posts[index];
        return OBPost(
          post,
          onPostDeleted: _onPostDeleted,
          key: Key(
            post.id.toString(),
          ),
        );
      })

我尝试让OBPost 小部件有状态并添加AutomaticKeepAliveClientMixinwantKeepAlive => true,但并没有改变任何事情,并且总体假设Flutter 使用key 属性来防止重新渲染项目。

更新:我还尝试将帖子小部件缓存在本地 List<Widget> _postsWidgets 变量中,也不会改变任何事情。

【问题讨论】:

  • 有什么更新吗?我也想知道同样的事情

标签: dart flutter


【解决方案1】:

您的列表看起来可以是无限滚动列表,因此我不建议您缓存 OBPost 小部件。你如何处理图像缓存?您是否将它们保存到本地文件系统?如果是,那么我建议您也有一个图像小部件的内存缓存。

为 ListView 使用 builder 背后的整个想法是不要创建大量的列表项小部件,而是出于内存和性能原因将它们保持在合理的最小值。

【讨论】:

  • 嗨 Roman,是的,我正在使用 pub.dartlang.org/packages/cached_network_image 将它们存储在本地文件系统上。做一个内存缓存听起来也是一个好主意,但是阅读 Github 问题,看起来它们可能已经缓存在内存中(github.com/flutter/flutter/issues/16241)。你对此有更多了解吗?也感谢您的回复!
  • 我检查了该库的代码,但我不确定它是否可以使用 ImageProvider 的默认行为,该行为应该在内存中缓存图像。我想你可以尝试调试一下,看看当你使用这个库时会发生什么。我还想说,重新创建 OBPost 对象完全没问题,你只需要找到一种方法来使用图像的内存缓存。
  • 您好 Roman,根据您的想法,我尝试使用普通图像,并且加载速度比使用 cached_network_image 更快。最后,我找到了这个库pub.dartlang.org/packages/flutter_advanced_networkimage,看起来它同时使用了内存和存储缓存。在我尝试过的所有方法中效果最好。
  • 太棒了!我很高兴我以某种方式帮助了你。感谢图书馆的链接,我自己可能也需要它。
猜你喜欢
  • 1970-01-01
  • 2020-07-25
  • 2020-12-24
  • 1970-01-01
  • 2020-03-09
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多