【问题标题】:Fastest Way To Display 100 or more images in Flutter在 Flutter 中显示 100 个或更多图像的最快方法
【发布时间】:2018-09-06 21:00:17
【问题描述】:

这个问题的目的是找到从图库中显示大量图像(20 或更多)的最佳方式。 我需要在设备上显示所有照片。如您所见,可能会显示很多图像,当我尝试使用不同的 Image.file() 小部件显示它们时,我的手机(LG G2)变慢,然后应用程序完全崩溃。

我认为问题在于我在 5 年的旧设备上加载了大量 4K 图像(超过 100 张)。实际上同时显示在屏幕上的图像实际上在 15 个左右,但我需要有类似画廊的东西,所以所有图像都在 GridView 中。

所以,我认为这不是最好的选择,也许有一个功能可以将图像缩小到 100x100 像素。但是上网查了一下,什么都没有。那么,有没有更好的办法呢?

我使用 Android 平台通道获取所有图像路径及其文件夹。

我将它们全部放在这样的列表中: [[“相机”、“存储/仿真/0/downloads/1.png”]等]

这是我得到的用户界面:(抱歉糟糕的设计)

屏幕上有三个主要组件,带有两个箭头的图标按钮: DropDownMenu 和 GridView。

IconButton 请求来自 android 的所有路径。在上述列表中。 DropDown 菜单在 onChanged 上有一个函数,它在 gridView 使用的 List 中创建所有卡片。

这是功能:

void _onChanged(String value) {
    setState(() {
      _currFolder = value;
      _photoCards = calculatePhotoCards();

    });
  }

calculatePhotoCards 是这样的:

List<Widget> calculatePhotoCards() {
    List<Widget> list = new List();

    for (int v = 0; v < _foldersAndPaths.length; v++) {

      if (_foldersAndPaths[v][0] == _currFolder) {


        list.add(Card(
            color: Colors.white,
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(20.0))),
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: new ClipRRect(
                borderRadius: new BorderRadius.circular(8.0),
                child: Image.file(
                  File(_foldersAndPaths[v][1]),
                  fit: BoxFit.cover,


              ),
            ),
          ),
        ));
      }
    }

    print(list);
    return list;
  }

其中 _foldersAndPaths 是包含其各自文件夹的所有路径的列表(如上所述),而 _currFolder 是 DropDownMenu 中的选定文件夹。

【问题讨论】:

  • 请包含您用来尝试加载和显示图像的代码。即使是旧手机,加载 20 张图片也不应该崩溃,所以很有可能发生了其他事情。
  • 而且仅供参考 - 默认情况下,flutter 确实会缩小图像大小和缓存,因此您不必担心太多。
  • 在我的 LG G2 上,正如我所说,我正在加载 100 多张,实际上将近 50 万张照片。我正在将代码添加到描述中
  • 对,但它不应该一次加载所有 100/500,而是加载当前屏幕上的那些。如果您尝试一次将所有 500 个都加载到内存中,那么您显然会遇到问题
  • 看看this answer(尽管忽略问题的代码 - 它不是最好的),以了解可能是什么问题......

标签: android ios flutter


【解决方案1】:

你需要添加cacheWidthcacheHeight

示例:

Image.network(
  shop.shopPic,
  width: 46,
  height: 46,
  cacheWidth: 46,
  cacheHeight: 46,
)

【讨论】:

  • 你知道在DecorationImage中是如何实现类似的吗?
【解决方案2】:

我决定实现它以查看它是否与图像大小等有关,因为过去对于远程图像存在一些问题。

当我实现它时,我遇到了和你完全相同的问题。我认为颤振确实将图像缓存缩放到合理的大小,但似乎并非如此。它实际上是将每个图像加载到内存中,这就是你崩溃的原因。不需要那么多图像就会耗尽内存,因为当它们被解码成像素时,它们已经非常大了。

Herehere 是关于这个(我自己提出了一个)针对颤振的错误。

所以不幸的是,我认为目前没有一种纯粹的颤振方式可以做到这一点。 pub 上有一个图像包可以缩小图像,但它直接在 dart 代码中执行,所以性能不是那么好。

在修复这些错误之前,您可能需要寻找针对此问题的特定于 android(以及特定于 iOS,如果您对此感兴趣)的解决方案。这将需要使用 android 缩略图创建器创建位图,然后保存该位图并将其 URL 传递回 Flutter,或者直接传递位图的字节。

对不起,我没有比这更好的答案了!

【讨论】:

    【解决方案3】:

    我正在使用 CachedNetworkImage,我在加载多个图像时遇到了问题,并且应用程序的内存超过了 3GB,因此解决方案是

    CachedNetworkImage(
        height: height,
        width: width,
        memCacheHeight: height, //add this line
        memCacheWidth: width, //add this line
        imageUrl: imageUrl,
      ),
    

    它将内存使用量从 3GB 减少到 60MB

    【讨论】:

    • 这不会减小下载图像的大小,但会降低图像在应用程序中显示的分辨率,从而降低比容器大得多的图像的内存成本显示在。
    • @croxx5f 是的,我有一个包含高质量图像的产品列表,并且相同的图像用作产品的缩略图和主图像,因此这是减少内存的最佳解决方案在产品列表页面中使用。
    • 是的,这是最简单的解决方案,如果您还想解决带宽问题,您需要以某种方式在后端实现图像调整大小,或集成第 3 方服务,以便下载图像只有所需的尺寸。其他增强可能是使用 CachedNetworkImage 包,这样您只需支付一次下载图像的费用。
    猜你喜欢
    • 2015-07-25
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    • 2021-06-24
    相关资源
    最近更新 更多