1

I have ImageView & one button on my ImageActivity. when the button is clicked the available images are listed, when one of them is clicked, it is loaded into the ImageView.

imageView xml:

   <ImageView
        android:id="@+id/imageView"
        android:layout_width="300dip"
        android:layout_height="300dip"
        android:src="@android:drawable/alert_light_frame" 
   />

Please see the code:

public class ImageActivity extends Activity {

    private static final int SELECT_PICTURE = 1; 
    private String selectedImagePath;
    private ImageView imageView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.comments_detail);

    imageView = (ImageView) findViewById(R.id.imageView);

      ((Button) findViewById(R.id.BtnBrowse))
       .setOnClickListener(new OnClickListener() 
       { 
          public void onClick(View arg0) 
          { 
              Intent intent = new Intent(); 
              intent.setType("image/*"); 
              intent.setAction(Intent.ACTION_GET_CONTENT); 
              startActivityForResult(Intent.createChooser(intent,"Select Picture"), SELECT_PICTURE);
         }
       });
}

    public void onActivityResult(int requestCode, int resultCode, Intent data) 
    { 
        if (resultCode == RESULT_OK) 
        {
             if (requestCode == SELECT_PICTURE) 
             { 
                Uri selectedImageUri = data.getData(); 
                selectedImagePath = getPath(selectedImageUri); 
                //System.out.println("Image Path : " + selectedImagePath);
                imageView.setImageURI(selectedImageUri);  
           }  
       } 
    } 

    public String getPath(Uri uri) 
    {  
       String[] projection = { MediaStore.Images.Media.DATA }; 
        Cursor cursor = managedQuery(uri, projection, null, null, null); 
       int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 
        cursor.moveToFirst();  
       return cursor.getString(column_index); 
    }


}

Issue: The issue is that when i click the button the available images are displayed, i selects one of them & it is loaded in the ImageView, when i repeat these steps few time the application throws throws the exception: java.lang.OutOfMemoryError: bitmap size exceeds VM budget

I goggled it & found that this issue is because of memory leaks but i am unable to find whats wrong with my code. Can anyone spend some of his valuable time to help me?

Thanks.

Yaqub Ahmad
  • 27,569
  • 23
  • 102
  • 149
  • why do you need to keep reference to imageView? – bestsss Nov 03 '11 at 18:53
  • Thanks @bestsss I need to save the selected image to the SQLite database – Yaqub Ahmad Nov 03 '11 at 19:00
  • but then you have 2 images at the same time, effective doubling the required memory. resolve the image before use, not onCreate... – bestsss Nov 03 '11 at 19:08
  • i dont have the source for imageview but i presume when you setImageURI it does (attempt to) load the new image and then flushes the existing, try to invoke `imageView.setBitmap(Bitmap.createImageBitmap(1,1, Bitmap.Config.ARGB_8888));` before setImageURI – bestsss Nov 03 '11 at 19:22
  • imageView.setBitmap(Bitmap.createImageBitmap(1,1, Bitmap.Config.ARGB_8888)); Not works for me. – Yaqub Ahmad Nov 03 '11 at 19:34
  • are you sure you are not keeping the image reference somewhere? – bestsss Nov 03 '11 at 19:42
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/4701/discussion-between-yaqub-ahmad-and-bestsss) – Yaqub Ahmad Nov 03 '11 at 19:49
  • possible duplicate of [java.lang.OutOfMemoryError: bitmap size exceeds VM budget - Android](http://stackoverflow.com/questions/1949066/java-lang-outofmemoryerror-bitmap-size-exceeds-vm-budget-android) – Sean Owen Apr 29 '13 at 20:08

2 Answers2

1

If you do a series of setImageURIs, you are loading a series of bitmaps into the view. If you are getting the java.lang.OutOfMemoryError: bitmap size exceeds VM budget exception, that implies that the imageView does not recycle the previous bitmap when you load a new one. So you

  • either need to encourage the imageView to recycle the previous bitmap - possibly with setImageView("")
  • or get the bitmap from the URI and use setImageBitmap(android.graphics.Bitmap) instead; then you can do setImageBitmap(null) and bitmap.recycle().
Sastrija
  • 3,284
  • 6
  • 47
  • 64
Torid
  • 4,176
  • 1
  • 28
  • 29
  • bestsss's suggetsion to do imageView.setBitmap(Bitmap.createImageBitmap(1,1, Bitmap.Config.ARGB_8888)) is how you should encourage the imageView to recycle (if you go that route). – Torid Nov 03 '11 at 19:34
  • i tried 'imageView.setImageBitmap(Bitmap.createBitmap(1,1, Bitmap.Config.ARGB_8888));' but the result is the same – Yaqub Ahmad Nov 03 '11 at 19:41
  • 2
    I found a post that suggested that you had to do setImageBitmap(null) before setting the 2nd and subsequent bitmaps - see http://stackoverflow.com/questions/7852943/what-does-bitmaprecycle-in-android-honeycomb-actually-do/7853636#comment9615375_7853636. That says it is Honeycomb onwards. What are you on? – Torid Nov 03 '11 at 20:32
-1

Well calling the system.gc() worked!! Before the image is assigned to the imageView, i called the System.gc(), to take care of memory & it works.

Look at the modified code:

public void onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    if (resultCode == RESULT_OK) 
    {
         if (requestCode == SELECT_PICTURE) 
         { 
            // calling GC to take care of memory, if you remove this one line of code
            // application will throw the error "VM out of memory error"
            System.gc();
            Uri selectedImageUri = data.getData(); 
            selectedImagePath = getPath(selectedImageUri); 
            imageView.setImageURI(selectedImageUri);  
       }  
   } 
} 

Thanks @Torid.

Can someone comment on it? is this correct way to call the GC in this situation?

Community
  • 1
  • 1
Yaqub Ahmad
  • 27,569
  • 23
  • 102
  • 149