Android bitmap memory leak

I put a 4x4 imageView in the action (BoardActivity) and the user can change the images by clicking them. With HTC Desire (Android 2.2.2), I got OOM (Out Of Memory) in about 30 minutes of intensive use -EDIT: the 16th launch of this operation is , but no other devices do this (android 2.1, android 2.2.1) . Is it possible that I made some mistake using a bitmap / image and what causes this error? First, I load the entire resource identifier into the map:

private Map<String, Integer> imageResourceMap; imageResourceMap = new HashMap<String, Integer>(); imageResourceMap.put("a", R.drawable.a); imageResourceMap.put("b", R.drawable.b); imageResourceMap.put("c", R.drawable.c); //... I store 55 drawable resourceId in this map 

Then I resize and save each image into a bitmap presented in Map:

 private static Map<String, Bitmap> 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; } 

I save ImageViews in an array and run all the images using this function:

 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; } 

When I need to change the image, I just change its resource:

 imageViews[i][j].setImageBitmap(imageBitmap.get("a")); 

And before I finish the action, I process the bitmap map:

 private void recycleImageBitmaps() { for (Bitmap b : imageBitmap.values()) { if (b != null) { b.recycle(); } } } 

In AndroidManifest.xml, I declared this activity "singleTask":

 <activity android:name=".game.board.BoardActivity" android:launchMode="singleTask"> </activity> 

In this application (game), we re-open this activity several times ... What am I wrong? Could this cause a "Out of Memory" error?

CORRECTION Fixed the getBitmapFromRes action as follows:

 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 still crashed on the 11th launch of this operation.

EDIT: This action (BoardActivity) is launched from Activity (MenuActivity), which has 4 imageButton, and works in Tabhost. ImageButtons declarations are as follows:

 <ImageButton android:id="@+id/game_menu_CreateButton" android:layout_width="120dip" android:layout_height="120dip" android:layout_alignRight="@+id/textView1" android:layout_alignTop="@+id/textView1" android:background="@drawable/create" android:layout_marginRight="1sp" android:layout_marginTop="10sp" /> 

When I launch BoardActivity from MenuActivity, I do not call finish() in MenuActivity, and when I call finish() in BoardActivity, I do not start a new intention, so it just goes back to the already open MenuActivity. And in the 16th round of this, I got OOM.

+6
source share
1 answer

To reduce memory, you can try the following:

  • After converting the drawings to bitmap images, you can set the imageResourceMap parameter to null. This will upload 3 drawings.
  • Avoid saving links to imageViews. You may keep ImageViews even after they are removed from the user interface.
  • Repeat beatmaps more often. Instead of just onDestroy, once you know that one bitmap is not in use, you can recycle it.

Edit: based on the conversation in the comments: the bitmap returned by BitmapFactory.decodeStream (fis, null, o) is not assigned to any variable and therefore is not processed. Android 2.2 and 2.3 will have leaks on this line.

+8
source

All Articles