I have a ViewPager with ImageView as child views. The ImageView displays Bitmap loaded from network and/or cached to local cache implemented as LruCache based class (from Android support library). The problem is that when the images are removed from LruCache, the GC seems to not release or release too late the bitmap memory. I very often get the exception OutOfMemory while loading new bitmap from network/disk even if the old bitmaps are removed from LruCache and from the holding ImageViews of ViewPager (I removed views from ViewPager). I read that sometimes (?) you must call the Bitmap.recycle (prior to Android 3.0) but this does not work. It also does not work on ICS (I do not call Bitmap.recycle there).
How to solve this problem?
The garbage collector won't recycle your bitmap if something is still referencing it. I would imagine that you have ImageViews hanging onto your bitmaps. ViewPager doesn't recycle Views so you'll need to clear out your ImageView when it's not being shown.
You can check out the BitmapFun sample from android developers site on how to display Bitmaps efficiently. The sample has a GridView and ViewPager of images already that you can refer to in building your app. Though the sample has some caching issue which I did some work around already. You can check it out here.
The problem isn't handling many images, it's that your images aren't getting deallocated when your activity is destroyed.
It's difficult to say why this is without looking at your code. However, this article has some tips that might help:
http://blog.booking.com/android-reuse-bitmaps.html
Related
I am still new to Android, and never had to deal with memory management in my previous experience.
In my android application, I have an activity with a TextView, a ListView, and ImageView. I have listeners for the textview and listview, and the code that changes the contents in all three of those views. The contents is stored in the arraylist. The source for the ImageView is stored in form of a String (filenames), and the code that makes the changes looks like this:
tv1.setText(myText);
imgView.setImageResource(myImage);
This worked perfectly well while I only had a few images to test the logic, but once I added more images, I started to get the OutOfMemory error. If I make the images smaller, I get that error a little later in the process, but I still get it.
At first, I thought that Android does not release the previous source, so I thought using recycle() before the reassignment will help. Instead, I've got another error when I try to change the source:
Cannot draw recycled bitmaps
It looks like I am missing some vital understanding about how the ImageView handles the source images. Does it assign the bitmap reference and then keeps the same reference, but somehow changes content?
Then, after reading this article, I realized I have a different kind of problem altogether, the one that might be solved by using the inBitmap. Yet, the documentation says the bitmaps have to be the same size for that, and mine are not.
I am thinking of converting my drawable to bitmap, then scaling it to some hard-coded dimensions, then using inBitmap. I guess my second question is - does this approach make sense? Are there any downfalls in scaling the images? And any examples would be appreciated, of course.
Thank you!
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.
I'm having serious issues with memory, and I'm looking forward to recycle bitmaps.
However, what my app is doing atm, is building a Gallery (yeah, the deprecated) with several bitmaps, and then, several Galleries.
So at the end of the day, the app looks like (LinearLayout style):
*Some webviews
*A Gallery with 7 images.
*Some webviews
*A Gallery with 10 images
and so on.
So what I'm thinking is... Once I've displayed those images, and them are on the screen, can those bitmaps be recycled?
Is there any way to recycle a whole Gallery component?
Thank you so much.
Edit:
I've tried soo many things. I'm still getting the error java.lang.IllegalArgumentException: bitmap size exceeds 32bits
This is my actual code:
BitmapFactory.Options bfOptions=new BitmapFactory.Options();
bfOptions.inDither=false; //Disable Dithering mode
bfOptions.inPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared
bfOptions.inInputShareable=true; //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
bfOptions.inTempStorage=new byte[32 * 1024];
bfOptions.inInputShareable=true;
bfOptions.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeFile(mUrls.get(position).getPath(), bfOptions);
inflatedImageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 120, 120, false));
As you can see, I've set many options to the Bitmap, aswell as resizing it, and lowering it's quality. Still happenning the same issue.
First you should never manually call system.gc, and generally there is no need to manually recycle bitmaps either. Let the operating system do what its best at, deciding when to take the huge hits to run garbage collection.
One of the reasons that gallery was deprecated is I am fairly sure it just loads all items as soon as it renders. And does not load them and recycle them on demand like a list view. Which means it is a huge waste of RAM and no amount of recycling will help you. In addition Gallery is very glitchy on 4.0+ phones, which is the majority of the Android user base at this point. I would strongly recommend you move away from using gallery.
There are two alternatives.
1) View Pager which is now built into the Support V4 library
2) HorizontalListView --> https://github.com/MeetMe/Android-HorizontalListView
Also be absolutely sure you are downsampling all images prior to loading them in the image views. To learn how read http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Ok. I solved the issue I was having; I had a linearLayout with gallery components and webviews. If I didn't render the webviews the app didn't crash.
So after some tweaks now it's working correctly without crashes:
wv_detail.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
wv_detail.setLayerType(View.LAYER_TYPE_NONE, null);
I'm creating a simple Gallery of drawables - each of them is almost the size of a screen, so they require quite much memory. For each entry I'm creating a custom LinearLayout with ImageView and TextView for the title. As most of you know, android Gallery doesn't recycle views so it gallery will crash easily on low-memory phones (after loading 4 drawables on 16mb ram limit, in my case).
Here's the simple question - how do you implement such gallery, so it won't run out of the memory? How do you recycle these images? A working code example would be great.
Few notes:
inSampleSize isn't a way to go, I can't scale these images down
Calling recycle() on Drawable's loaded from resource is impossible, as it will crash on Android 4.0+ (it will recycle the drawable in their internal cache)
Don't ask me to post the code, as there is no.
You shouldn't be using Gallery because it's deprecated. Especially since there isn't any code written so far. The documentation suggests using a HorizontalScrollView or ViewPager.
I feel a ViewPager is what your looking for because it will only keep at most 3 pictures in memory and handels all the recycling for you. Here is a post with more information about how to implement one android viewPager implementation
I'm developing an Android app with a list view that contains lots of drawables.
Most of them are the same so I'm trying to use a HashMap that returns the same allocated bitmap when it's needed but still there are lots of allocations and GC actions so that the list gets stuck from time to time when scrolling.
What can I do to optimize the performance in such case?
Caching method - loadImage Using google code
mImageWorker.loadImage(pic_url, holder.pic);
holder.*some bitmap*.setImageBitmap(Utility.getBitmap(context, id); //can be one of 5 bitmaps do I use caching with a hashMap
see this example
this will helps you....
don't put so much process under the getView() method . this will lack the listview scroll performance
if you want to do image crapping or drawable to bitmap conversition or anything .. just do all process
before loading adapter.. and just assign values for each row in getView()...
Try to use lazy loading technique using caching, you can find many tutorial on the web:
You have to see this SO thread
Also see this:
Multithreading For Performance, a tutorial by Gilles Debunne.
This is from the Android Developers Blog. The suggested code uses:
AsyncTasks.
A hard, limited size, FIFO cache.
A soft, easily garbage collected cache.
A placeholder Drawable while you download.
If you want to optimize the code, try lazy loading concept for loading images in list. Please refer: Lazy Load images on Listview in android(Beginner Level)?