How to clean up bitmap resources - android

I wanted to ask this question that was asked a few times before. Sorry if I am re-itterating but it is not clear to me as to what is the best solution here.
The question is "how to clean ImageView bitmap resource after its been used so we don't have references to it in memory?".
Here is an example:
Screen 1 redirects to Screen 2
Screen 2 contains control A (preview of large photo)
Control A contains ImageView B
ImageView B is set when control A is initiated
Everything works fine the first time around. Once control A is done I redirect from Screen 2 to Screen 1. At this point all references of control A or ImageView B or Bitmap that its using should be dead. THEY ARE NOT!!!
I've tried all kinds of solutions including bitmap.recycle(), adding finalize() into Control A, System.gs() and nulling control in variouse places such as onStop() and onDestroy(), and everything else that's on screen 2, nothing works!
The problem is when I revisit the screen second time around so going from screen 1 to screen 2 (i.e. creating preview of photo again) I get out of memory exception. It is my understanding that the reference of the previous bitmap is not cleaned up.
How do I KILL it just before I redirect back to Screen 1?
One thing I noticed. If I reduce the size of the photo by, say cropping or making a smaller size of the image everything goes smooth, few times... before I get same issue. So basically it just takes a bit longer to fill up.
I would really appreciate some solution here as this is critical.

You probably have a memory leak , this video might help you in finding the problem Google I/O 2011: Memory management for Android Apps.
Note : pre 3.1 bitmaps are store in VM heap memory but in native memory , which causes lot of problems in noticing leaks,for further info refer the video

Have a look at how WeakReference is used.

Related

Android ImageViews Causing Memory Leak?

I'm the sole developer on an app for the company I work for. I'm new at app development and I've nearly finished the app but when I was testing, I noticed the heap size grows while navigating the app up to 3x the starting amount until GC runs and knocks it back down. I ran MAT and saw that it had to be something with bitmaps. I am currently changing the icons to an "on" state every time they are touched. This means I just changed the icons to a different colored image to give the visual appearance of being "tapped" such as below.
ImageView callButton = (ImageView) findViewById(R.id.callButton);
callButton.setImageResource(R.drawable.call_on);
They are then turned "off" from onResume such as below.
ImageView callButton = (ImageView) findViewById(R.id.callButton);
callButton.setImageResource(R.drawable.call_off);
I do this for every icon throughout the app. My question is whether this is causing the memory leak from creating so many ImageViews. Should I set them to null onDestory?
No, you do not need to set bitmaps to null in onDestroy. Especially not if you're using images from resources, which references are kept to in Resources anyway. What you may want to consider is using a StateDrawable and changing the state rather than switching drawable's all the time, just for your own sanity. But this kind of usage shouldn't be causing OOMs unless you have a lot of images or other issues.
Release your bitmaps as soon as possible using setImageDrawable(null) like -
callButton.setImageDrawable(null);

Out of memory exception on inflating layouts

I am getting random out of memory exceptions in my app caused by inflate exceptions.
I have 7 fragment (difficulty) activities which launch their own activities via buttons. Each fragment has a scroll view with 30 buttons (levels).
I have set it up so that i can swipe across to each fragment and the fragment takes up the entire screen.
Occasionally when i swipe a few times and then select a random button from a group of 30 it will crash. It tries to load the activity and gives an out of memory exception with an inflate exception on a random line. The line always falls on an imageView or imageButton in the xml file. The activities that load are a grid of imageViews and imageButtons.
I do not get the exception much but it is something i want to fix. I have looked at many other out of memory exception questions although none have helped me. I have done a Memory analyser test and it shows nothing out of the ordinary.
I believe that the imageViews and imageButtons are using too much memory, although i only ever have one activity open at once.
It IS because of your images that are loading. When you load an image and you move around the page and view another image the heap increases. As you continue the process of viewing random images the heap grows even more until your app crashes. It's like stacking books on a glass table. You either move(cache) a book(image) or the glass(app) breaks. You should use an imageloader to load your images.
https://github.com/nostra13/Android-Universal-Image-Loader
You've mentioned that it always falls on an ImageView and ImageButton - and this is the clue to solve this problem. You get OOM 'cause background resource of this view has high resolution and takes a lot of memory. Try to lower resolution of this image.
Also you've mentioned that you have a ScrollView and this means that you keep in memory every 30 items. Probably you'd better change it to RecyclerView backed by adapter.
Just had the same problem and I'd like to simplify all the things said here:
Simply: reduce your images sizes.
Don't use 1080X1920 images... It's too high res.
Such image, even if compressed, when deployed will catch about 1080X1920X4B = 8.2MB (The GPU has to deploy it to it's full original resolution... That's why compression won't help but reducing the needed memory size...) and this i RAM that we're talking about..
Take Gimp or Photoshop and down scale the image to, say, 1/4: 540X960, and you won't feel the difference.. Belive me, been there already.
Beware of the memory consumption of images and videos.
Hope this helps,
James

Possible memory leak in Square/Picasso for Android

I am part of a team developing a commercial media app. Part of the functionality is to allow the user to customise a ViewGroup montage of ImageViews with their own images retrieved either from Gallery or direct from Camera. I am using the following Picasso call to do this:
mPicasso.load(uri)
.resize(newWidth, newHeight)
.into(container);
where mPicasso is Picasso.with(appContext()) and newWidth and newHeight are dimensions calculated from the source height and width such that aspect ratio is maintained and the resulting image is 1MP. Typically, the sources are between 8 and 16MP.
If I have a montage of say, eight ImageViews, and I keep adding images to each one in turn, the app eventually crashes. Device only has so much memory, right? Eventually if you keep adding infinite images you're going to run out. What really concerns me, however, is that the app will crash half-way through replacing the eight images. To be clear, you've added your eight images and you've gone back to the top and started replacing those images with different ones and you get to roughly the fourth before the crash.
I would have expected that once an image has been replaced, the old one would be cleaned up. I can fix this by reducing the max size down to 100KP but the problem with that is I imagine I am just delaying the crash. Furthermore, the user has the ability to zoom the image and with such a low resolution, it starts to look knarly quite quickly.
I have posted the crash log here:-
https://gist.github.com/mylesbennett/452c992f6912039ea62d
because it's too long to paste direcly in stackoverflow.
Any suggestions of workarounds/ fixes etc. would be greatly appreciated.
(the crash point in TemplateImageView.isScaleInitialised is where the app is attempting to allocate memory to a nine-value float array:
float[] values = new float[9];
so I am guessing that this is just the straw that broke the camel's back)

how to clear memory when it is full because of using too many backgrounds in android

Hi guys i am new to android and i posted a question a week ago in this link which basically stated that i was getting a java.lang.outofmemory error when i was using a lot of different backgrounds for my activities.
why am I getting errors when I use different backgrounds in xml
So as a new developer I have searched and searched for a solution as to how to clear the memory as i go from activity but none have been clear or precise. Then i stumbled across this site http://androidactivity.wordpress.com/2011/09/24/solution-for-outofmemoryerror-bitmap-size-exceeds-vm-budget/
which described exactly what i was going through except they use 10 activities and i am only using 4. However when i implemented his code it my project i ended up with null pointer exceptions and after fiddling with his code I ended up back were i started with the same out of memory error.
So can anybody direct me to someone who can show me how to have as many backgrounds as i want with out running out of memory. Or does android as great as it is does not let you simply use more than a certain amount of backgrounds? help?
It's not that there is a limit on the amount of backgrounds, but each background image you load is a loaded into memory as a bitmap and held there until the activity is destroyed. If you are opening multiple activities one after another, each background image will need to be held in memory and so eventually you will get an out of memory exception.
If you set a large background image, you will also experience some blocking on the ui thread, while the image is loaded into memory.
One way around this that worked for me was to use an imageloader. This decodes the image off the ui thread, caches it on disk, loads it into memory and if memory is running low, will clear an image from memory and fallback to the disk cache. You may get a slight delay/fade in as the image is loaded but this is not so bad visually, and when loaded once, will load straight away if you go back to that activity.
Check out Picaso Picasso which is really easy to implement and a great api or Universal Image Loader.
My layouts were all RelativeLayouts and the first child (will be behind all other views) was an ImageView with scaleType centercrop and width and height set to match_parent. When each activity loads (onCreate), just grab a reference to the imageview in your layout and set the required background image using your ImageLoader of choice.
The other option is to have multiple copies of your background image in your resources, with each one resized to perfectly fit your resolutions of choice (drawable-mdpi/-hdpi/-xhdpi etc). This way, you ensure you are never loading images that are way bigger than you need to be displayed and your app will be more forgiving in terms of memory consumption.

Images take up too much heap space

I've come across a strange problem - I'm making an android game and noticed a lag every few seconds and checked the logs when I noticed the garbage collector was being called every few seconds for 50-150ms a go.
I've whittled this problem down to the images, when I launch my title screen activity, using one background image (150kb) - the messages i get are:
4% free (8009k/8259k)
GROW HEAP to 9.012MB
GC_CONCURRENT freed 1kb (9178k/9479k)
Which is a lot of heap space for an image and three buttons. When I remove the image, I get no warnings or messages (not sure how to force an output on heap-space, but I hope it's at normal levels)
The code for the activity image isn't that exciting as it's just a title screen, but:
<ImageView
android:id="#+id/backgroundImage1"
android:contentDescription="Image"
android:src="#drawable/openingscreen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top"
/>
When I launch the actual game the heap size increases again (only by a few mb's) -- the weird thing is when I didn't have the title screen, the heap space for the main game was still 12 or so mb's - so I'm thinking maybe the image is holding a reference to everything else. Although I tried using a background image of 1 pixel in size and this caused no problems.
Secondly, the code for images inside the gameThread:
mPlayer = Bitmap.createScaledBitmap(mPlayer, mCanvasWidth / 15, mCanvasHeight / 8, true);
canvas.drawBitmap(mPlayer, xPosition, yPosition, null);
I did hear somewhere that scaling bitmaps can cause memory problems, but that doesn't really add up with everything else.
Yes,a lot of developers while developing has faced this situation.
What i would ask you to do is a thorough study check of what exactly this heap is,how the garbage collector handles it,how can you efficiently use or even scale bitmaps
You could first start with going through this video
Google Android Memory Management
Next in the android developers site, go through in detail
Displaying bitmaps efficiently
Last and final thing start a habit of using MAT(Memory analyzer Tool),there are tutorials,lessons a lot of blogs on how to use it and finding out where and why the app is being deprived of memory
Following formular tells you how much heap space an image take: width x height x 8 bytes. So an image thats all white but large in size will still take a lot of heap space.
Just updating, I found out the main problem in my code and managed to get it running smoothly, I doubt anybody else is stupid enough to make the same mistake but I'll post my solution just in case!
I was re-sizing my images every iteration of the game, I somehow didn't realize I put the code in there, changed it so it re-sizes them at the very start and that's it. But there it is, I doubt this solution will help anybody, but perhaps one day it will!
Kevin.

Categories

Resources