Is it necessary to set a Bitmap to null after recycling it, so that its memory can be freed?
In the following code:
private static Bitmap bmpConcatHV() {
Bitmap bmp = BitmapFactory.decodeResource(resId);
Bitmap bmp2 = concatVertically(bmp, bmp);
bmp.recycle();
bmp = null;
Bitmap bmp3 = concatHorizontally(bmp2, bmp2);
bmp2.recycle();
bmp2 = null;
return bmp3;
}
There are Lint warnings:
The value null assigned to 'bmp' is never used
The value null assigned to 'bmp2' is never used
Both bmp and bmp2 are local variables, so no.
BitmapFactory.decodeResource(resId);
bitmap has two part of information when loaded into memory
1- information about bitmap ==> exists in java used memory
2- information about pixels of bitmap (byte of array) ==>exists in c++ used memory
Bitmap.recycle() is used to free the memory of C++.
Garbage Collection will collection the part of java and the memory
Garbage Collection work when need memory but i need to use this reference now so will use
bmp = null; here i handle the part of java and be safe to make it null
Related
I'm developing my first Android app. I have a method that creates two bitmaps and returns a third bitmap which is an overlay of the second bitmap on top of the first bitmap. So basically, I don't need the two bitmaps once the third bitmap is created.
I've read some posts and articles about releasing bitmap memory and I'm a bit confused on how to handle it.
Do I have to release the bitmaps myself? If yes, what is the proper way to do so?Are they released when the method is finished? Should I just let the garbage collector release it?
public static Bitmap bitmapResizeOverlay(Context context, Uri selectedImage, int maxWidth,
int maxHeight, #DrawableRes int overlayImageResource) {
Bitmap selectedBitmap = bitmapResize(context, selectedImage, maxWidth, maxHeight);
Bitmap overlayBitmap = BitmapFactory.decodeResource(context.getResources(), overlayImageResource);
return overlayBitmapToBottom (selectedBitmap, overlayBitmap);
}
selectedBitmap.recycle()
method is used always in when you want clear the memory occupied with bitmap.
The down side of not recycling the bit map could be OOM (out of Memory Exception)
I have recycled the bitmap variable and when I again tried to use the same variable I have some strange errors with reference to recycle. Any solution to this issue ?
java code:
image1.recycle();
image1=null;
LogCat:
05-29 11:35:42.139: E/AndroidRuntime(695): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap#2bbad018
05-29 11:35:42.139: E/AndroidRuntime(695): at android.graphics.Canvas.throwIfRecycled(Canvas.java:1038)
05-29 11:35:42.139: E/AndroidRuntime(695): at android.graphics.Canvas.drawBitmap(Canvas.java:1078)
Returns an immutable bitmap from the specified subset of the source bitmap. The new bitmap may be the same object as source, or a copy may have been made.
It seems that the createBitmap functions have the potential to re-use the bitmap that you provided. If that is the case, then you shouldn't recycle the temporary bitmap since your final bitmap is using it. One thing you can do is
if(tempBitmap != finalBitmap) {
tempBitmap.recycle();
}
That should only recycle the tempBitmap when it isn't the same as the finalBitmap. At least that seems to be what the documentation is implying.
Once you recycle the bitmap its memory is freed. That's mean that bitmaps data are gone from the memory. If you want to use again the same variable you have to decode the Bitmap againg .
if (image1 == null || image1.isRecycled()) {
image1 = BitmapFactory.decodeStream()
}
You can have check before recycling the bitmap, as like :
if (img != null && !img.isRecycled())
{
img.recycle();
img = null;
System.gc();
}
Here img is bitmap.
Try this type error is sloved.
If I create an object and assign it to a variable:
Obj obj1 = null;
obj1 = myFunction(params);
(here myFunction creates a complex object)
And later I reassign the variable:
obj1 = myFunction(otherparams);
Does in that moment a memory leak occur, because I did not destroy the previous object?
Here is the real situation:
Bitmap bmp;
bmp = drawMyBitmap(3);
//... some code
bmp = drawMyBitmap(4);
Will a memory leak happen here?
Of cource, I know that I must call bmp.recycle, but I can't do it, because the real code is the following:
Bitmap bmp;
bmp = drawMyBitmap(3);
imageView.setImageBitmap(bmp);
//... some code
// if I try to do recycle here - I receive java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
// But I need to recreate bitmap every some minutes
bmp = drawMyBitmap(4);
imageView.setImageBitmap(bmp);
So, how can I recycle the bitmap and avoid memory leaks?
As I understand, your problem is just you can't recycle your Bitmap cause it's used.
It's pretty naive, so maybe it's wrong, but do this:
imageView.setImageBitmap(bmp);
//... some code
Bitmap tmp = bmp;
bmp = drawMyBitmap(4);
imageView.setImageBitmap(bmp);
tmp.recycle(); // As it's not anymore referenced by the ImageView, you can recycle the Bitmap safely
I didn't test it. Give feedback.
In the first case, you will release the first object's reference so the garbage collector will destroy it, leaving the second one live on memory because of new reference.
In the second case, if you are setting bitmaps to ImageViews, you can not recycle them because the view will not have the bitmap to draw the image and it will throw to you a bitmap recycled exception, so you are not "leaking" to much memory keeping 2 bitmaps on memory.
Try to use bitmap options to create them to optimise your memory comsuption if you want.
Bitmap bmp;
bmp = drawMyBitmap(3);
imageView.setImageBitmap(bmp);
//... some code
// if I try to do recycle here - I receive java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
// But I need to recreate bitmap every some minutes
Bitmap temp = bmp; //try this
bmp = drawMyBitmap(4);
imageView.setImageBitmap(bmp);
temp.recycle();
I wanna create an bitmap array. Is it possible?
If yes, which is the way to declare the Bitmap array. and how to initialize it?
Thank you
You could use an Arraylist :
ArrayList<Bitmap> bitmapArray = new ArrayList<Bitmap>();
bitmapArray.add(myBitMap); // Add a bitmap
bitmapArray.get(0); // Get first bitmap
or simply an Array of bitmap like :
Bitmap[] bitmapArray = new Bitmap[];
Nevertheless be careful with the size of your image. You will probably have some trouble if you try to store lot of big image.
Yes it is possible,
If bitmap1 and bitmap2 are objects of bitmap. I can assign them to an array as follows.
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(),R.drawable.a_thumb);//assign your bitmap;
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(),R.drawable.anotherimage);//assign your bitmap;
Bitmap[] arrayOfBitmap = {bitmap1, bitmap2};
Thanks
Deepak
Just like any array, for example:
Bitmap[] bitmaps = new Bitmap[] { BitmapFactory.decodeResource(...) /* etc. */ }
There is nothing special in the fact that the objects in array are Bitmaps.
You can make bitmap aaray in android like this,
byte[] bMapArray= new byte[buf.available()];
buf.read(bMapArray);
Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
image.setImageBitmap(bMap);
Use this android developer documentation for details.
Use this too
All the above/below solutions are possible but a common case is actually using a HashMap as it is the case with Image Downloaders and async bitmap loaders.
A Bitmap is an object as may others (String arrays, Integer arrays etc...) so you might modify those methods you find also for storing bitmap arrays.
I am loading a bitmap from a resource like so:
Bitmap mBackground = BitmapFactory.decodeResource(res,R.drawable.image);
What I want to do is make some changes to the bitmap before It gets drawn to the main canvas in my draw method (As it would seem wasteful to repeat lots of drawing in my main loop when it isn't going to change). I am making the changes to the bitmap with the following:
Canvas c = new Canvas(mBackground);
c.drawARGB(...); // etc
So naturally I get an exception
java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor
So to avoid that I made a copy of the bitmap so that it is mutable
Bitmap mBackground = BitmapFactory.decodeResource(res,R.drawable.image).copy(Bitmap.Config.ARGB_8888, true);
Which avoid the problem however it sometimes causes OutOfMemoryExceptions, do know any better ways of achieving what I want?
Use decodeResource(Resources res, int id, BitmapFactory.Options opts) and specify inMutable in the options.
http://developer.android.com/reference/android/graphics/BitmapFactory.html
You'd better use RapidDecoder.
import rapid.decoder.BitmapDecoder;
Bitmap mBackground = BitmapDecoder.from(res, R.drawable.image)
.mutable().decode();
Works for API level 8.
Instad of yours:
Bitmap mBackground = BitmapFactory.decodeResource(res,R.drawable.image);
Use:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
Bitmap mBackground = BitmapFactory.decodeResource(res,R.drawable.image, options);