【问题标题】:Android loading drawable into ImageView taking a lot of memoryAndroid将drawable加载到ImageView中会占用大量内存
【发布时间】:2015-06-26 00:55:30
【问题描述】:

我遇到了问题。

我正在将 9 drawables 动态加载到 9 imageViews 中。 (drawables 每次都不同)drawable id 存储在对象类中,所以当我加载这个drawable 时,我使用imageView.setImageRessource(myObject.getRessourceId());ImageRessource 设置为imageView 一切正常,但是当加载 9 个可绘制对象时,我在 Android 内存监视器上看到分配内存达到 80MB,我认为这不正常......(是吗?)

我尝试了不同的方法来解决它:

  • 使用 Picasso 库加载可绘制对象。
  • 使用BitmapFactory.decodeResssource 创建位图,然后 在 imageView 上设置ImageBitmap。

使用我尝试的所有技术,它占用了 80MB 的分配内存。

我尝试在 ldpi (~30Ko/image) 和 xhdpi (~87Ko/image) 中使用不同的图像分辨率,但它不会改变加载的每个图像的任何内容,它需要大约 5MB 的分配内存...

所以我的问题是:如何减少为这些图像分配的内存?

提前谢谢你,如果需要,我可以提供部分代码。

问候

PS:ImageViews 是在onCreate() 方法中动态创建的。

【问题讨论】:

  • 加载缩小的图像而不是原始图像,你能分享代码吗?

标签: android performance memory drawable


【解决方案1】:

这很正常,你记忆的最大敌人是图像。另请注意,图像在内存中占用的空间比在磁盘上要多。加载时间长也是正常的。解决方案是只加载所见的大图像,并使用缓存下次更快地加载它们(您不需要再次下采样)。这是一篇带有示例项目的文章:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

【讨论】:

  • 您是对的,但可绘制对象最多加载 1 次,因此我认为没有必要将其保存在缓存中。但谢谢您的回答
  • 好吧,您仍然可以对它们进行下采样,以仅根据需要获取尽可能多的 msmory。使用缓存来避免每次都这样做是个好主意。
  • 感谢您的链接,我减少了分配的内存。但是要以可接受的质量显示我的图像,它需要大约 60MB 的 RAM。是正确还是过分?
  • 我想没关系。您会发现现在的结果会随着设备的分辨率而变化,分辨率越低,使用的内存就越少,因此旧设备将能够处理它。我很高兴你放弃了使用:)
  • 没关系!我现在保持在 40MB 以下!谢谢你:)
【解决方案2】:

根据图像的性质,这实际上是可以的。由于使用了压缩算法,现代图像的文件大小不一定与它在内存中的大小有关。在内存中,本来应该很小的文件被扩展为实际的位图数据,这意味着在 RAM 中将占用比在 sd-card/disk 上更多的数据。

但是,来源(以及图像)将有助于进一步分析。

您还可以查看某些查看器中的图像,并尝试确定在该查看器中加载时它占用了多少 RAM。您可能会对此类图像占用的大小感到惊讶。这就是为什么具有严重依赖图像的主题的 UI 如此消耗内存的原因。

【讨论】:

  • 是的,这是真的,但由于 Bojan Kseneman 的链接,我可能会找到解决方案。我会尝试设置位图的高度和宽度,因为实际上,大的可绘制对象是在小图像视图中加载的,所以也许它是解决方案。我现在就试试这个。
【解决方案3】:

感谢 Bojan Kseneman 的链接,我将分配的内存减少到 30Mb。我正在使用这个:

imageView.setImageBitmap(Util.decodeSampledBitmapFromResource(getResources(), id, 150, 150));

Util 是我项目的一个 Utility 类

使用这些方法:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                         int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

还有

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 2014-07-20
    相关资源
    最近更新 更多