【发布时间】:2014-07-18 17:40:04
【问题描述】:
我正在开发一个游戏,我在运行应用程序时使用BitmapFactory 加载了 52 个Bitmap files。我收到OutOfMemoryError。那是因为drawable 文件夹中的图像是.JPG 而不是.PNG?请告诉我如何解决这个问题。
【问题讨论】:
标签: android bitmap bitmapfactory
我正在开发一个游戏,我在运行应用程序时使用BitmapFactory 加载了 52 个Bitmap files。我收到OutOfMemoryError。那是因为drawable 文件夹中的图像是.JPG 而不是.PNG?请告诉我如何解决这个问题。
【问题讨论】:
标签: android bitmap bitmapfactory
JPG vs PNG 没关系,因为当您加载位图时,您会将它们解压缩为原始数据(基本上与 bmp 相同)。未压缩,每个位图使用 4*width*height 字节。根据您的图像有多大,它可能非常大。我建议使用具有固定大小的 LRUCache 来仅在内存中保存您实际需要的图像,并剔除未使用的图像。
【讨论】:
我在我的应用程序中处理 196 张 png 图片,当我尝试加载所有图片时也遇到了内存不足的问题。我的图像是 png,这意味着将它们从 jpg 转换为 png 并没有帮助。
我不知道这是否是最佳解决方案,但我所做的是在第一次调用时从我的主要活动的 OnCreate() 方法启动一个 IntentService。在内部,我检查是否已将较小版本的图像存储在内部存储中。如果已经创建了较小的版本,我会维护它们的列表,并在需要显示它们时在我的活动中使用它们。如果它们不存在(在用户第一次安装应用程序时发生),或者缓存从该应用程序的设置中清除,我会通过调用 decodeSampledBitmapFromResource() 以所需的宽度和高度来创建它们。所需的宽度和高度可以存储在 xml 文件中,并针对不同的屏幕。下面提供了我用于在保持图像纵横比的同时调整大小的函数。
/**
* Calculate in sample size.
*
* @param options the options
* @param reqWidth the req width
* @param reqHeight the req height
* @return the int
*/
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;
}
/**
* Decode sampled bitmap from resource.
*
* @param res the res
* @param resId the res id
* @param reqWidth the req width
* @param reqHeight the req height
* @return the bitmap
*/
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);
}
【讨论】: