Android 将可绘制对象加载到 ImageView 中占用大量内存
Android loading drawable into ImageView taking a lot of memory
我有问题。
我正在将 9 drawables
动态加载到 9 imageViews
中。 (drawables
每次都不同)drawable id 存储在对象 class 中,所以当我加载这个 drawable 时,我使用 [=16] 将 ImageRessource
设置为 imageView
=]
一切正常,但是当加载 9 个可绘制对象时,我在 Android 内存监视器上看到分配内存达到 80MB,我认为这不正常...(是吗?)
我尝试了不同的方法来解决它:
- 使用 Picasso 库加载可绘制对象。
- 使用
BitmapFactory.decodeResssource
创建一个Bitmap然后
在 imageView 上设置 ImageBitmap。
使用我尝试过的所有技术,它需要分配 80MB 的内存。
我尝试在 ldpi (~30Ko/image) 和 xhdpi (~87Ko/image) 中使用不同的图像分辨率,但它不会为加载的每个图像改变任何东西,它需要大约 5MB 的分配内存...
所以我的问题是:如何减少为这些图像分配的内存?
先谢谢你了,如果需要我可以给出部分代码。
此致
PS:ImageViews
是在onCreate()
方法中动态创建的。
这很正常,记忆的最大敌人是图像。另请注意,图像在内存中占用的空间 space 多于在磁盘中的空间。加载时间长也是正常的。解决方案是只加载与看到的一样大的图像,并使用缓存在下次更快地加载它们(您不需要再次下采样)。这是一篇带有示例项目的文章:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
根据图像的性质,实际上这可能没问题。由于使用的压缩算法,现代图像的文件大小不一定与其内存中的大小相关。在内存中,原本应该很小的文件被扩展成实际的位图数据,这意味着在RAM中占用的数据比在sd-card/disk.
上要多
但是,来源(以及图像)将有助于进一步分析。
您也可以在某些查看器中查看图像,并尝试确定在该查看器中加载图像时占用了多少 RAM。您可能会对此类图像占用的大小感到惊讶。这就是为什么具有严重依赖图像的主题的 UI 如此消耗内存。
感谢 Bojan Kseneman 的 link,我将分配的内存减少到 30Mb。我正在使用这个:
imageView.setImageBitmap(Util.decodeSampledBitmapFromResource(getResources(), id, 150, 150));
Util is a Utility class of my project
使用这些方法:
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;
}
我有问题。
我正在将 9 drawables
动态加载到 9 imageViews
中。 (drawables
每次都不同)drawable id 存储在对象 class 中,所以当我加载这个 drawable 时,我使用 [=16] 将 ImageRessource
设置为 imageView
=]
一切正常,但是当加载 9 个可绘制对象时,我在 Android 内存监视器上看到分配内存达到 80MB,我认为这不正常...(是吗?)
我尝试了不同的方法来解决它:
- 使用 Picasso 库加载可绘制对象。
- 使用
BitmapFactory.decodeResssource
创建一个Bitmap然后 在 imageView 上设置 ImageBitmap。
使用我尝试过的所有技术,它需要分配 80MB 的内存。
我尝试在 ldpi (~30Ko/image) 和 xhdpi (~87Ko/image) 中使用不同的图像分辨率,但它不会为加载的每个图像改变任何东西,它需要大约 5MB 的分配内存...
所以我的问题是:如何减少为这些图像分配的内存?
先谢谢你了,如果需要我可以给出部分代码。
此致
PS:ImageViews
是在onCreate()
方法中动态创建的。
这很正常,记忆的最大敌人是图像。另请注意,图像在内存中占用的空间 space 多于在磁盘中的空间。加载时间长也是正常的。解决方案是只加载与看到的一样大的图像,并使用缓存在下次更快地加载它们(您不需要再次下采样)。这是一篇带有示例项目的文章:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
根据图像的性质,实际上这可能没问题。由于使用的压缩算法,现代图像的文件大小不一定与其内存中的大小相关。在内存中,原本应该很小的文件被扩展成实际的位图数据,这意味着在RAM中占用的数据比在sd-card/disk.
上要多但是,来源(以及图像)将有助于进一步分析。
您也可以在某些查看器中查看图像,并尝试确定在该查看器中加载图像时占用了多少 RAM。您可能会对此类图像占用的大小感到惊讶。这就是为什么具有严重依赖图像的主题的 UI 如此消耗内存。
感谢 Bojan Kseneman 的 link,我将分配的内存减少到 30Mb。我正在使用这个:
imageView.setImageBitmap(Util.decodeSampledBitmapFromResource(getResources(), id, 150, 150));
Util is a Utility class of my project
使用这些方法:
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;
}