java.lang.OutOfMemoryError 在 viewFlipper 中显示图像列表时
java.lang.OutOfMemoryError While Displaying image list in viewFlipper
我正在尝试在我的应用程序中使用动态磁贴图像。我在某些设备 (API>22) 上测试了该功能,它们可以正常工作。但是现在我正在 API 22 上进行测试,但我在标题中遇到了错误。我搜索了该站点,发现它特别有用 OutOfMemoryExceptionGridView。但是我正在将我的图像(直接从 res 文件夹)加载到一个数组,然后使用 viewflipper 制作幻灯片
我如何更改我的代码块(以修复主 OOME),因为我上面链接的内容使用位图,而我直接调用 res id。
这是我的代码:
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
int[] images = {R.drawable.img1, R.drawable.img2, R.drawable.img3}; //store images into array
viewFlipper = view.findViewById(R.id.firstTile); //main tile to have slideshow
for (int image : images) {
flipperImages(image); //performs the slideshow per image
}
}
public void flipperImages(int image) {
ImageView imageViewFirstTile = new ImageView(getContext());
imageViewFirstTile.setBackgroundResource(image);
viewFlipper.addView(imageViewFirstTile);
viewFlipper.setFlipInterval(12500);
viewFlipper.setAutoStart(true);
viewFlipper.setInAnimation(getContext(), android.R.anim.slide_in_left);
viewFlipper.setOutAnimation(getContext(), android.R.anim.slide_out_right);
}
如何修复此实现的主要错误(直接调用图像的 res id)?
如果可以缩小图像以避免加载全尺寸图像,我会考虑将其作为第一步。如果显示它们的 window 只是大小的一小部分,则无需将全尺寸位图加载到内存中。在您当前的方法中,图像未被二次采样,因此整个 Bitmap
以其完整大小加载到内存中。所以你的内存中有 3 个全尺寸 Bitmap
。
要对图像进行子采样,请参见以下代码。 (来源:https://developer.android.com/topic/performance/graphics/load-bitmap)
/* reqWidth and reqHeight would be the dimensions of your ImageView or some other preferred dimensions. For example, if your Bitmap is 500 X 500 and your ViewFlipper/ImageView is only 100 X 100, passing 100 as reqWidth and 100 as reqHeight will subsample the image until it's dimensions are close to the 100 X 100. This will largely shrink the size loaded into memory. */
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;
}
我正在尝试在我的应用程序中使用动态磁贴图像。我在某些设备 (API>22) 上测试了该功能,它们可以正常工作。但是现在我正在 API 22 上进行测试,但我在标题中遇到了错误。我搜索了该站点,发现它特别有用 OutOfMemoryExceptionGridView。但是我正在将我的图像(直接从 res 文件夹)加载到一个数组,然后使用 viewflipper 制作幻灯片
我如何更改我的代码块(以修复主 OOME),因为我上面链接的内容使用位图,而我直接调用 res id。
这是我的代码:
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
int[] images = {R.drawable.img1, R.drawable.img2, R.drawable.img3}; //store images into array
viewFlipper = view.findViewById(R.id.firstTile); //main tile to have slideshow
for (int image : images) {
flipperImages(image); //performs the slideshow per image
}
}
public void flipperImages(int image) {
ImageView imageViewFirstTile = new ImageView(getContext());
imageViewFirstTile.setBackgroundResource(image);
viewFlipper.addView(imageViewFirstTile);
viewFlipper.setFlipInterval(12500);
viewFlipper.setAutoStart(true);
viewFlipper.setInAnimation(getContext(), android.R.anim.slide_in_left);
viewFlipper.setOutAnimation(getContext(), android.R.anim.slide_out_right);
}
如何修复此实现的主要错误(直接调用图像的 res id)?
如果可以缩小图像以避免加载全尺寸图像,我会考虑将其作为第一步。如果显示它们的 window 只是大小的一小部分,则无需将全尺寸位图加载到内存中。在您当前的方法中,图像未被二次采样,因此整个 Bitmap
以其完整大小加载到内存中。所以你的内存中有 3 个全尺寸 Bitmap
。
要对图像进行子采样,请参见以下代码。 (来源:https://developer.android.com/topic/performance/graphics/load-bitmap)
/* reqWidth and reqHeight would be the dimensions of your ImageView or some other preferred dimensions. For example, if your Bitmap is 500 X 500 and your ViewFlipper/ImageView is only 100 X 100, passing 100 as reqWidth and 100 as reqHeight will subsample the image until it's dimensions are close to the 100 X 100. This will largely shrink the size loaded into memory. */
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;
}