Утечка памяти при просмотре растровых изображений Android
Я добавил 4x4 imageView к действию (BoardActivity), и пользователь может изменять изображения, щелкая их. С HTC Desire (Android 2.2.2) я получил OOM (Out Of Memory) примерно за 30 минут интенсивного использования-EDIT: 16-й старт этой деятельности-, но никакие другие устройства не производят это (Android 2.1 и Android 2.2.1). Возможно ли, что я допустил некоторую ошибку с использованием растрового изображения / изображения, и это вызывает эту ошибку? Сначала я загружаю все ID ресурса в карту:
private Map imageResourceMap;
imageResourceMap = new HashMap();
imageResourceMap.put("a", R.drawable.a);
imageResourceMap.put("b", R.drawable.b);
imageResourceMap.put("c", R.drawable.c);
//... I store 55 drawable's resourceId in this map
Затем я изменяю размеры и сохраняю каждое изображение в растровом изображении, представленном на карте:
private static Map imageBitmap;
private void loadBitmaps(int imagesSize) {
for (String s : imageResourceMap.keySet()) {
Bitmap tmp = getBitmapFromRes(imageResourceMap.get(s), imagesSize);
imageBitmap.put(s, tmp);
}
}
private Bitmap getBitmapFromRes(int resId, int imageSize) {
Bitmap b = null;
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
InputStream fis = getResources().openRawResource(resId);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
int scale = 1;
if (o.outHeight > imageSize || o.outWidth > imageSize) {
scale = (int) Math.pow(2, (int) Math.round(Math.log(imageSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = getResources().openRawResource(resId);
b = BitmapFactory.decodeStream(fis, null, o2);
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return b;
}
Я храню imageViews в массиве и инициализирую все изображения с помощью этой функции:
private static ImageView[][] imageViews;
private ImageView getImage(String name) {
MyImageView item = new MyImageView(this, i, j, c + "");
item.setImageBitmap(imageBitmap.get(name));
item.setAdjustViewBounds(true);
return item;
}
Когда мне нужно изменить изображение, я просто меняю его ресурс:
imageViews[i][j].setImageBitmap(imageBitmap.get("a"));
И непосредственно перед тем, как закончить упражнение, я перезаписываю растровую карту:
private void recycleImageBitmaps() {
for (Bitmap b : imageBitmap.values()) {
if (b != null) {
b.recycle();
}
}
}
В AndroidManifest.xml я объявил эту деятельность "singleTask ":
В этом приложении (игре) мы снова открываем это действие несколько раз ... Что я не так сделал? Может ли это привести к ошибке Out Of Memory?
КОРРЕКЦИЯ Исправил getBitmapFromRes следующим образом:
private Bitmap getBitmapFromRes(int resId, int imageSize) {
Bitmap tmp = null;
Bitmap b = null;
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
InputStream fis = getResources().openRawResource(resId);
tmp = BitmapFactory.decodeStream(fis, null, o);
fis.close();
int scale = 1;
if (o.outHeight > imageSize || o.outWidth > imageSize) {
scale = (int) Math.pow(2, (int) Math.round(Math.log(imageSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = getResources().openRawResource(resId);
b = BitmapFactory.decodeStream(fis, null, o2);
fis.close();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(tmp != null){
tmp.recycle();
tmp = null;
}
}
return b;
}
HTC все еще потерпела крах на 11-м запуске этой деятельности.
РЕДАКТИРОВАТЬ: Это действие (BoardActivity) запускается из Activity (MenuActivity), которая имеет 4 imageButton и находится в действии Tabhost. Объявления imageButtons выглядят так:
Когда я запускаю BoardActivity из MenuActivity, я нет звонокfinish()
на MenuActivity, и когда я звонюfinish()
в BoardActivity, я нене начинать новое намерение, поэтому оно просто возвращается к уже открытому MenuActivity. И в 16 туре я получил ООМ.