如何在我的网格视图中显示电话画廊图像

时间:2018-08-23 07:18:01

标签: gridview memory-leaks flutter

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

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]),
                              ),
                            ),...

这确实显示了前几张图像,但是崩溃却很慢,并且在“运行”控制台中提供了以下内容

Lost connection to device

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

1 个答案:

答案 0 :(得分:1)

有些事情在这里引起问题。

  1. 您正在使用收缩包装,听起来像是大量对象。
  2. 您正在使用Gridview.count而不是构建器
  3. 您的图像没有预定义的高度

我将解释为什么每个都不是个好主意:

1)使用收缩包装:

如文档中所述,Shrinkwrap是:

  

scrollDirection中滚动视图的范围是否应为   由所查看的内容确定。

一个简单的示例来说明这一点,即您的网格是否应该占据整个屏幕,但是其中只有2个项目。如果启用了ShrinkWrap,则网格将仅占用与两个项目相同的空间。如果关闭了wrapwrap,它将占据整个屏幕,但项目仍将位于顶部。

不同之处在于,启用ShrinkWrap后,GridView每次滚动时都必须计算其子级的高度,以确保最大高度没有变化。

在大多数情况下,除非您有特定的用例(例如,您想在每次删除项目时向上移动的网格,下面都有一个删除按钮),否则您不想使用ShrinkWrap。您绝对不希望对大量项目使用ShrinkWrap,因为这意味着网格在确定列表的最大范围之前需要对每个项目进行布局。

2)使用GridView.count:

通过使用count类型的构造函数之一,网格视图将立即构建(至少部分构建)列表中的每个项目。 As it says in the docs:

  

要创建带有大量(或无限)子代的网格,请使用   GridView.builder构造函数,其中一个   SliverGridDelegateWithFixedCrossAxisCount或一个   SliverGridDelegateWithMaxCrossAxisExtent用于gridDelegate。

这样做,它允许gridview仅实例化屏幕上的那些项目(如果设置了cacheExtent,则在每一侧都缓存了一部分)。

3)没有预定义的高度:

这是一个常见错误。由于网格中的每个项目都没有特定的尺寸,因此他们委托孩子寻找尺寸。但是,由于图像在加载之前没有大小,因此可能会引起问题。

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

我建议为网格的图块设置大小,或者至少设置长宽比,以便它们可以立即确定其高度。如果需要,可以在加载图像后将它们委托给图像的大小,但最好对每个图像使用BoxFit。