In my game I have 3 activities: Main menu -> Sub-menu -> Game screen. So when user is playing in the Game screen, first two activities are inactive, but not destroyed.
There is a nice background image in each layout. The image itself is quite small (40k), but on large screen (say Galaxy tablet), it takes up to several megs of memory.
After removing background from first two activities, memory usage in third activity falls from 18M to 13M!
Is there any way to keep backgrounds and to recover all this wasted memory?
I have experienced a similar issue due to background images in layouts. The normal size of a memory allocation of an image should be height*width*4 bytes (in mode ARGB_8888, the default mode).
If you see and allocation of 18MB when showing an activity there must be some problem. Check if you are placing your background images in the drawable folder. In that case, the system must scale that image to the specific density of the screen, causing a big memory overhead.
Solutions:
Place a specific version of the background image in each drawable folder (mdpi, hdpi, xhdpi...) so the system does not have to perfom any scaling process.
Place the background image in a special resource folder called "drawable-nodpi". The system won't try to scale images placed in this directory so only an streching process is carried out and the memory allocated will be the expected.
More information in this answer
Hope this helps.
Why dont you finish the previous activities when starting the new activity (C).
Then you can override the onKeyDown method in activity C to start the previous activity (B)
I think my problem is same to yours, this solution will help you.
Why does the normal pictures allocated a lot of memory?
You can use /res/drawable-nodpi, the background pictrue only take half of the memory size.
I would suggest to override onPause() or onStop() in your activity. In there, you can release the background (by calling layout.setBackgroundDrawable(null))
Related
I am using itemTouchHelper to remove a cardView from a RecyclerView on swipe
my cardview is simple it just has a text and an image
but when i swipe to remove the card disappears but is never taken out of memory (i am saying this because the memory of the image never goes away and it causes an out of memory exception)
my code is very simple so i was wondering if there was a step i was messing that tells the recycler view to remove from memory?
my code is exactly like this one
Usually, images are loaded in android memory, scaled according to device screen resolution requirements, and kept there till the process dies or, is killed or, is collected by garbage collector.
It is possible that your image size in card view (or other images in your res folder) is/are large, and images after scaling by android is occupying too much of memory, to cause memory exception. Try reducing size of your image (Try compare size with the icon sizes that google icons has, they all are less than a Kb, amazing !).
If the above does not work, then create a drawable-nodpi folder in your res folder and put large size images in this folder, this will indicate android to not to scale these images and render it as it is. (make sure you test in all screen devices after following this approach, because now the image won't scale in different screen sizes).
Finally, if none of the above helps try running : System.gc() after there is a card swipe action performed by user. This will run garbage collector and your image will be removed from memory. (This approach does not guarantee garbage collector working in all devices, so make sure that you try for above two approaches, they should work).
Hope this helps !
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
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.
Actually I have for so long wish to know how to present graphics in a proper way.
In an activity, I have the following:
a background (png, full screen, 768*1280, 1.36MB)
3 icons (each icon has pressed and not pressed: 2 states, using 1 png 400 * 400, 300KB each), i.e. 3 icon * 2 pic * 300KB = 1.8MB
some more textviews
When the app starts off and directly goes to this activity, everything is ok, the activity can be presented properly.
Yet somehow when the app has run for some other activities, and then goes to this activity through a dialog box, then most of the time errors will occur, as follows:
Out of memory on a 15728656-byte allocation.
Question:
I have researched for sometime and some say to bitmap.recycle(), yet how to implement? through the onCreate? or actually 400*400 is too big?
If I want to change the background of an activity upon users' choice, i.e. when he presses button A, the background changes to bgdA, presses button B will change background to bgdB... in that way how that can be achieved?
Many thanks!
Depending on where your asset is stored is the amount of memory it might take, since scaling factor is calculated between the difference of densities, this is a little gray area because I haven't found any official android documentation that backs this info up, however I've seen that error so many times and this is the way I handle it.
1.- If you don't have the asset in the proper drawable-(density), this will cause problems because depending on the devices you are actually supporting, you should put the asset in drawable-xxhdpi or drawable-xhdpi, you will notice how the memory will decrease considerably
2.- If you don't want to mess with densities because it's a generic image which don't have much details(like a simple background), then add the asset in the drawable-nodpi folder, it will prevent android from trying to scale the asset it self..
3.- As good practice, try to create the asset with the proper size for the proper densities, 400 x 400 seems like too much for an icon, this will also prevent you from OOM, not only in this activity, but for other activities that might also need to load a good amount of assets, giving scalability to your app..
Always take on count that leaving the "resize" of an Image to the OS might cause huge amounts of memory allocated because the OS will try to resize it based on the formula width * height * 4bytes, the 4 byes are for ARGB of each pixel, 1 byte per color or alpha, so if your image is for example 1090 * 1920, it could easily become internally 8.3MBs even tho the actual image size is only a few KBs, and if it tries to scale it, it might double it's size too.
Hope this Helps
Regards!
Make sure you have a copy of your image for every drawable folder in you res, for example if you runnig your app on the S4 phone and you don't have all the images in the drawable-xxhdpi folder you will run out of memory even with reasonably small images.
Also if you need to change background at run time use setBackgroundResource.
Hope it helps
This is the common problem in android here is the proper solution
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
In easy words you have to scale the image down according to your requirement
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.