Loading images onto ImageView in xml takes more memory?
I Have an Activity with around 7 imageviews(just like the app tray in any android phone.)
I am loading the images for each of the imageviews in the xml. Does this cause OutOfMemoryError?
Is there a way to recycle these?
Yes it is possible to attach drawable images to ImageView and you can remove them when you need.
imageview.setBackgroundResource(R.drawable.image);
or
imageview.setImageDrawable(drawable);
It does not cause any out of memory issue. Link to Doc
I have had this problem when i was loading Images. Sometimes this error can only be seen in Android emulator, sometimes this crashes the app in the mobile device too.
I solved this problem by following two steps:
Re-size the image if the resolution is too high.
Not having too many image objects open at the same time.
You can help the garbage collector out too, by assigning the image object to NULL when it is no longer necessary.
Unless necessary i would prevent opening too many images at the same time.
The factor by which you have to re-size, will depend on the actual size of the image.
Few Tips to address memory issues in Android:
1). Never use local variables to store large data / bitmaps specially in loops, As it will create un-necessary objects. I prefer class/instance variables in such situations. Try not to persist data unless it is required.
2). Avoid making calls to View.findViewById(..) wherever you can. Romain Guy has clearly stated in Google I/O 2010 that this method is costly (takes some KBs of memory to run), so call this method smartly like using ViewHolder which will consume less memory.
3) Use String pool effectively and use StringBuilder/StringBuffer when you are doing heavy operations with strings. Make sure that you are aware when you have to use StringBuffer as it is synchronized and again costly in comparison to StringBuilder.
Related
I'm using Jake Wharton's DiskLruCache lib.
I'm curious about app performance, caching strategy, using caching both in a view and across a whole application. Most of the time, the image won't change.
Let's say for example I have a 320x320 photo on my server. I open the stream, save the image.
In my list views, I show bitmaps and in the detail, I show a larger image. Should I save a thumbnail bitmap too? Is that more efficient?
What is your experience with sharing the cache "object" across the entire app (let's say I have multiple views that might leverage the same data. What are the issues with this?
For the sake of performance and currency, what if the image changes on the server. What's the best strategy to know that it's changed? I don't have access to modified date. Only size and yet, I don't really want to query size every time either. Set a flag in the app on the server and then query the flag?
In a traditional application (if there is such a thing), what's the best practice for clearing the cache from time to time? (indent weirded out.)
(I was inspired to write this after seeing all of the performance improvements by Facebook in iOS. I don't have billions to do caching but I would like to at least be smart about it! LOL)
A lot of these answers depend on the type of app you're writing, how important image updates are (and how likely images will change, etc), and total images produced. Aside from disk caching, you should be using memory caching as well, especially in ListViews and other areas where the same images will be scrolled through repeatedly. Look at LruCache and read the Caching Bitmaps entry from Google.
320x320 is probably too big for a listview, you will likely want to create thumbnails (depending on device, and how you're implementing your listviews).
1) You should be using Disk caching fairly aggressively (how you define that is up to the app you're writing). Use the external storage directory, and if they have a few GB left over, it's not an issue if you take 100 mb for your app for instance. It can all be cleared away if it's ever needed anyway.
2) There shouldn't be an issue. Disk IO (even to a flash medium) should never be handled on the main thread. Use AsyncTasks to load the images. There can only be one main foreground activity at once anyway, and while an activity is sleeping, it shouldn't be trying to read from the disk anyway.
3) Again this depends on how you're implementing your app. You should be able to get additional information when retrieving the file (even Apache can tell your app the last modified date).
3.1) You can have a sqllite db that keeps track of how often certain images are used, and most recent read. If the most recent read is a few days old, let that image expire.
Edit: There's a library from Jake Wharton now called Picasso that I would recommend using, which handles the Network/local IO as well as memory and disk caching. Check it ou here: http://square.github.io/picasso/ . A lot of what you will need to do can be accomplished with one line: Picasso.with(this).load(imageFileURL).into(imageView);
i am developing one application related to graphics, in this application i am using
lots of images and drawing on it.and all activities are running until my flow does not
get completed.so what should i do for assign large heap size to run smoothly my
application. Or any other way to run application smoothly .. i have no idea about
memory management right now . i am using only BitmapDrawable to display images and also
system.gc() to garbage collection . also use this
Runtime.getRuntime().runFinalizersOnExit(true);
Runtime.getRuntime().gc();
Runtime.getRuntime().freeMemory();
can anybody help me .. thanx in advance
Have you tried using Java weak references so that these images are automatically garbage collected? This blog post explains that well. Also, you can use Guava Collections CacheBuilder for the images.
It not possible to increase Heap Size.Its fixed.But you an do some calculation to remove some waste of memory.
1) If you are using Bitmap then recycle it using bitmap.recycle() when it use became over, this will be garbage collected.
2)Try to remove unnecessary reference from your object if there is no use of them.
3)Try to use Local Variable and avoid Static function and variable
Hope it help you :)
Android does not allow you to adjust your heap size for Java code—you’re stuck with a value of about 20MB (perhaps more on newer devices). Always remember to recycle your bitmaps.
I'm developing an android app that takes photos from camera or from library and does some stuff on them. The point is that after some use the application crashes. I have tried to make every possible optimization I could think of, ex call gc when possible, null the images when I leave an activity and even remove activities from the cache. But I still get out of memory errors and the app crashes.
Any suggestions on how to avoid such errors? Or even how to efficiently load images from drawables folder . Or any efficient way to throw all not needed objects when the activity changes so as to only use the needed memory for the active activity??
i had similar problems and ended up tracking them down to particular images. out of my 400 images there where three that where huge (file size wise). so i would check that all of your images have similar file size (usually it is directly correlated with image size)
also aren't bitmaps pretty big? how big is your average picture?
Did you manage Bitmap objects? If so, you have to call Bitmap.recycle() method.
Bitmap.recycle() API documentation
I knw this is one of the most discussed question but I couldn't figure out my way with the questions available here.
I'm decoding the bitmap as below
BitmapFactory.decodeFile(sdCardPath);
While executing above line randomly system running out of memory. This is not happening always . For example if I try to decode same image 3 times, it might go out of memory 3rd time or even 4th time. This error observed randomly.
How to solve this issue??
Thanks for your time in advance
First, if this is a bitmap that you are referencing from your assets, I would recommend moving it to your res/drawables folder, and access it as a drawable. If this is not the case, you are making too many references to this image without, as #VargaPeter pointed out, garbage collecting. The best way to garbage collect when using multiple bitmaps is to call recycle(), however System.gc() is often used as well (though in practice, you should use recycle(). If you are still having problems, you must either (a) allocate more space using the Android NDK (discouraged), or (b) use a smaller bitmap image (recommended). I know for certain there are posts discussing option b in several places on this site, as I had this same problem once before.
The Bitmap that you get back probably isn't garbage-collected because of a lingering reference.. Try to use the same reference if the app's design allows, or reusing a small number or references...
We have an Android application that throws out of memory error on Android 1.6. It is working fine on 2.0 onwards. We are trying to cut down on the runtime memory usage at this point.
We were thinking of reusing images – such as the background image of each screen. Is it possible to load the background image once in the memory at the time of app launch and reuse this cached copy in each screen rather than each screen loading the same background image increasing the overall footprint in the RAM?
We understand that there many other ways and best practices around runtime memory usage. But at this point, we just wanted to know whether this “image reuse” approach is really feasible?
If yes, how can we do this? Will it at all save any memory or the Android OS will still create multiple copies of the same asset for each screen not giving any benefit from the memory perspective?
Thank you very much for your time in reading my post.
If that background image is loaded as a Drawable from a Resource, it's bitmap data is already shared between all Drawables created that way. So no, it probably wouldn't benefit you in your particular case.
Yes you can reuse images.
It is usually done for ListViews where each row contains the same image.
In this case, you can get the Bitmap once in the constructor of your adapter, and reuse it in the getView() method, so you don't have to load it for each row. This trick is presented here
In your case, you could load your background bitmap in the onCreate() method of your main activity, save it as a public static attribute and then re-use it in all your activities.
But I think it won't make that much of a difference and surcharge the code for nothing.
As you are working on tweaking your UI, I suggest you watch the 2009 Google I/O Presentation by Romain Guy, if you did not see it yet. It shows a lot of useful tricks for boosting an UI's performances, especially when it comes to Bitmap manipulation.