如何在我的网格视图中显示电话画廊图像 [英] How to display phone gallery images to my grid view

查看:104
本文介绍了如何在我的网格视图中显示电话画廊图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In fact this is a theoretical question in some way because I did achieve this, but have a memory blackout due to loading all images that exist in my phone. The following is how I store the images into a list.

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);
    }...

因此,我拉出列表中的路径,并在网格视图中显示如下.

So, I pull out the paths in the list and show in my grid view as following..

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

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

This does show the first few images, but slowly crashes and it gives me the following in the 'run' console

Lost connection to device

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

I have to restart. But of course it does same thing when trying to load. What am I doing wrong here?

推荐答案

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

There are a few things that are causing issues here.

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

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

I'll explain why each of these is a bad idea:

1)使用收缩包装:

如文档中所述,Shrinkwrap是这样的:

Shrinkwrap is, as it says in the docs:

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

Whether the extent of the scroll view in the scrollDirection should be determined by the contents being viewed.

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

A simple example to explain this is if your grid is supposed to take up the whole screen, but only has 2 items in it. If you have ShrinkWrap enabled, the grid will only take up the same amount of space as the two items; if shrinkwrap is off it will take up the entire screen but the items will still be at the top.

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

The difference is that with ShrinkWrap enabled, the GridView has to calculate the height of its' children every time it scrolls to make sure that the maximum height hasn't changed.

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

Most of the time, you don't want to be using ShrinkWrap unless you have a specific use case (i.e. a grid with a delete button underneath that you want to move up each time an item is deleted). You definitely don't want to be using ShrinkWrap with a large amount of items, as that means that the grid needs to layout each of those items before it can figure out the maximum extent of the list.

2)使用GridView.count:

通过使用count类型的构造函数之一,网格视图将立即构建(至少部分构建)列表中的每个项目. 在文档中说:

By using one of the count type constructors, the grid view will immediately build (at least part) each and every item in the list. As it says in the docs:

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

To create a grid with a large (or infinite) number of children, use the GridView.builder constructor with either a SliverGridDelegateWithFixedCrossAxisCount or a SliverGridDelegateWithMaxCrossAxisExtent for the gridDelegate.

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

By doing this, it allows the gridview to instantiate only those items on the screen (and a bit cached on each side if you set cacheExtent).

3)没有预定义的高度:

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

This is a common mistake. Because each item in the grid doesn't have a specific size, they delegate to their children to find a size. However, because Images don't have a size until they are loaded, this can cause problems.

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

Basically, each image is starting with a height of close to zero. That means that many, many images can fit on the screen so the phone tries to load all of the up. That's what is probably causing your memory issue and crash.

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

I recommend setting a size for the tiles of your grid or at least setting an aspect ratio so they can determine their height by that immediately. If you need to, you could have them delegate to the size of the image once it has loaded but it would probably be better to simply use a BoxFit for each of the images.

这篇关于如何在我的网格视图中显示电话画廊图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆