Gridview 如何在我的网格视图中显示手机图库图像

Gridview 如何在我的网格视图中显示手机图库图像,gridview,memory-leaks,flutter,Gridview,Memory Leaks,Flutter,事实上,这在某种程度上是一个理论问题,因为我确实做到了这一点,但由于加载手机中存在的所有图像,导致内存中断。下面是我如何将图像存储到列表中的 final Directory extDir = await getExternalStorageDirectory(); extDir.list(recursive: true, followLinks: false) .listen((FileSystemEntity entity) { print(entity.path);

事实上,这在某种程度上是一个理论问题,因为我确实做到了这一点,但由于加载手机中存在的所有图像,导致内存中断。下面是我如何将图像存储到列表中的

final Directory extDir = await getExternalStorageDirectory();

extDir.list(recursive: true, followLinks: false)
  .listen((FileSystemEntity entity) {
    print(entity.path);

    /* check for image and save */
    if(entity.path.endsWith("jpg")
    || entity.path.endsWith("png")
    || entity.path.endsWith("gif")
    ) {
      _PhoneImages.add(entity.path);
    }...
因此,我拉出列表中的路径,并在我的网格视图中显示如下

new GridView.count(
              shrinkWrap: true,
              physics: new ClampingScrollPhysics(),
              crossAxisCount: 2,

              children: new List<Widget>.generate(_PhoneImages.length, (index) {
                return new GridTile(
                  child: new GestureDetector(
                      child: new Stack(
                        children: [

                          new Card(
                            color: Colors.blue.shade200,
                            child: new Center(


                              child: new Image.file(
                                new File(_PhoneImages[index]),
                              ),
                            ),...

我必须重新开始。当然,它在尝试加载时也会做同样的事情。我在这里做错了什么?

这里有一些事情导致了问题

您使用的是包覆面提取,听起来像是大量对象。 您使用的是Gridview.count,而不是生成器 您的图像没有预定义的高度 我将解释为什么这些都是一个坏主意:

1使用包覆面提取:

正如文档中所述,包覆面提取是:

滚动方向上滚动视图的范围是否应为 由正在查看的内容决定

一个简单的例子来解释这一点,如果你的网格应该占据整个屏幕,但其中只有2个项目。如果启用了包覆面提取,网格将只占用与两个项目相同的空间量;如果“包覆面提取”处于禁用状态,它将占据整个屏幕,但项目仍将位于顶部

不同之处在于,启用包覆面提取后,GridView必须在每次滚动时计算其子对象的高度,以确保最大高度没有更改

大多数情况下,您不希望使用包覆面提取,除非您有一个特定的用例,即在每次删除项目时都希望向上移动的下方带有删除按钮的网格。您肯定不希望对大量项使用包覆面提取,因为这意味着网格需要先布局这些项中的每一项,然后才能计算出列表的最大范围

2使用GridView.count:

通过使用一个计数类型构造函数,网格视图将立即构建列表中至少部分的每一项

要创建包含大量或无限多个子网格,请使用 GridView.builder构造函数具有 SliverGridDelegated带有FixedCrossAxisCount或 SliverGridDelegateWithMaxCrossAxisExtent用于gridDelegate

通过这样做,它允许gridview仅实例化屏幕上的那些项目,如果设置cacheExtent,则在每一侧缓存一点

3无预定义高度:

这是一个常见的错误。因为网格中的每个项都没有特定的大小,所以它们会委托给其子项以查找大小。但是,由于图像在加载之前没有大小,这可能会导致问题

基本上,每个图像都从接近零的高度开始。这意味着很多很多图像可以放在屏幕上,因此手机会尝试加载所有图像。这可能是导致内存问题和崩溃的原因


我建议为网格的平铺设置一个大小,或者至少设置一个纵横比,这样它们就可以立即确定它们的高度。如果需要,您可以让他们在加载图像后指定图像的大小,但最好是对每个图像使用BoxFit。

感谢您的解释,这是一个很好的教训。不过,我确实使用了固定高度,也使用了一定尺寸的boxfit。我认为这可能是收缩包装或项目本身的大小,这是造成内存过载。我找到了一种方法来调整与图像包,他们看起来很好,现在没有崩溃,但暂时。我使用收缩包装的原因是因为我在页面视图中使用了网格视图。当前的网格在第二页。我不认为在这种情况下,你仍然不需要收缩包装,除非你做了一些奇怪的事情。默认情况下,页面视图水平滚动,而网格至少垂直滚动,包络收缩仅影响网格滚动的方向。如果网格和页面视图方向相同,则情况不同。不管怎样,如果设置了包覆面提取、使用“计数”或图像没有高度,您将遇到问题-您需要修复这三个问题。如果您添加了足够的代码来运行示例,我可以尝试一下。
Lost connection to device