where each page is a fragment with a different image set as a background. Since i need to ensure it scrolls smoothly without lag, i have set the offscreenpage to 20(the number of items in the viewpager)but i am getting this error quite oftenly:
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
i have already compressed the images to the maximum(Compressed JPEGS),any idea how i can solve this issue?
There is a nice article in the Training section of the Android developers site: http://developer.android.com/training/displaying-bitmaps/index.html... it shows you how to use caching mechanisms in you android applications. You can adopt this in your ViewPager implementation.
I would load/unload the background images dynamically as you switch fragments. They should load fast enough to not notice, especially if you use an animation to hide the transition (fade in/fade out). Or better yet, load 4 or 5 of them (2 in each direction) so you only see the fading if you scroll very quickly.
The bitmap size depends on the pixel density of the image. Try to reduce your background image MPx.
Related
So, I have been using this amazing library Glide for showing native images in my gallery app. I am using ViewPager with FragmentStatePagerAdapter to show full size images. The pager's off screen limit is 1 (default to save memory). I am using this code to load images into ViewPager in my fragment:
Glide.with(getActivity())
.loadFromMediaStore(uri)
.asBitmap()
.signature(new MediaStoreSignature(mimeType, dateModified,
.into(mImageView);
Now, I am facing some issues here like:
Images take quite some amount of time to load (if not cached). So, while user is scrolling through the viewpager blank screen is shown while image is loading which is what I want to avoid. Is there any way I can do this? Maybe by precaching images?
Sometimes, while scrolling through large size images (mainly Camera photos) OOM Exception is thrown and user is left with blank screen as no image is loaded. This also happens when I am shifting from potrait to landscape mode. So, I tried to use methods like atMost() -- which degrade the quality of image further as images are already loaded in RGB_565 and approximate() which is also causing OOM. How can I achieve maximum image quality without getting OOM exceptions?
For the second issue, I was thinking to load lesser quality images for the off screen items and then enhance quality when they come on-screen. Is it possible?
I have also tried to use ARGB_8888 but the result was same: OOM exception.
TL;DR
Make sure the ImageView has match_parent or fixed dp as dimensions
wrap_content makes Glide load full resolution Bitmaps.
.placeholder() shows an image instead of empty space while loading large bitmap
.thumbnail(float) loads a downsampled version fast while the bigger image is loading in the background
Also look around the Glide issues, maybe you find something helpful.
Details
I would be curious what the xml is for the ImageView, because my guess is it's wrap_content which results in loading images at full resolution into Bitmaps (using a lot of memory). If that's the case I would suggest using match_parent or fixed dp to lower the resolution. Note: you won't use detail, because currently the image is downsampled at render time anyway, just pulling that forward to decoding phase.
You also have to make sure that your app doesn't have constraints for memory usage. Can you load 3 (off screen limit = 1 means 1+current+1 pages) camera photos into Bitmaps without Glide? Again, assuming this is full resolution, it should be possible to store 3 screen size amount of bytes in memory with or without Glide, but you have to guide Glide to not load at full resolution.
You can load smaller sized image via .thumbnail(), it accepts a full Glide.with... not including .into() OR there's a shorthand parameter which is just a percentage (in 0.0 ... 1.0), try the latter first. It should decode the image much faster, especially with a really small number like 0.1 and then when higher quality one finishes it's replaced.
So the simpler option is to add .thumbnail() to your current load. A more convoluted one involves to start loading a lower resolution image with .sizeMultiplier() at the same time the Fragment's view is created and then start loading the high resolution one when the ViewPager has changed page. This helps with peeking the pages.
Alternatively you can just use a .placeholder() while the image is loading so it's not empty space, but "something" there.
Regarding using ARGB_8888 (32 bit per pixel): if you increase the memory consumed by Bitmaps (compared to RGB_565 (16 bit per pixel) don't expect to get run out of memory later. Once you get it working with 565 you can try increasing, but until then it's futile trying.
Also look around the Glide issues, maybe you find something helpful.
I know this question is asked several times, but still clarity to my situation would be helpful.
I am showing some images in 2 column grid view. When user taps on an image, I am displaying the image in ViewPager. The Image which is displayed in gridview is about 200X200px and I want to show the same image with enlarged size say about 800X800px in ViewPager in a DialogFragment.
The Actual size of images are huge with different resolutions. I have followed the link http://developer.android.com/training/displaying-bitmaps/index.html and I have scaled down images to size which is required for my app. In ViewPager fragment dialog I am also recycling the image with bitmap.recycle() and calling System.gc() explicitly(I know this is a bad practice) at PagerFragment onDestroy. But even then I am getting Out of memory error. On top of it, I am encountering this issue only in Android 4.2.1 (Nexus 7) but not on Android 4.1.2( Samsung Tab) and Android 4.4(Nexus 7).
For later 2 android versions, I do not have to call even System.gc(). It works very well without this. I have checked Viewpager with some 300 - 400 images. But for former after scrolling 60 images, App is crashing with OutOfmemory error. To resolve this I have used a workaround for now android:largeHeap="true" which I think is very bad for myapp and could not digest it.
I really appreciate if anyone who can help me avoid android:largeHeap="true".
In my app, I have to show around 6000 images in GridView and also an enlarged image in ViewPager linked to GridView. I am loading only 20 images from FileSystem asynchronously while scrolling gridview.
Thanks in advance...
Use an LRUCache to hold the images. Make that the only thing that holds a Bitmap that's not currently on screen. That way the older bitmaps will be kicked out and garbage collected quickly.
i am new to android and i want to set an image as background to different fragments in an activity.But the images are to large that they make my application to increase in memory and i don't want this. The activity have 6 different fragments and each have different background, here i set the background images from drawable.
i referred this.but i didn't get correct solution.
How could i make them so that the memory size of images will be less?
Android - Reduce the memory usage of Bitmap Drawables
On this concrete case you have 2 options:
1 - Set the image as background on the root view of your fragment Layout. Doing that you'll avoid out of emmory errors, but the image will be scalled to fullfill the whole screen, so it could be diformed.
2 - Use Picasso library http://square.github.io/picasso/ to load the file images. It can be helpful to manage memory issues.
Also, the best thing you could do before starting is to reduce the size of the images using some software such as https://tinypng.com/.
Hope it helps
My app is getting crashed (throws OutOfMemoryError) when I try to load images in a ViewPager. Here are the details.
All the images are 720*1280 in dimension with 100-150KB in size.
I even tried using Fragments in a Viewpager to load images.. but after sliding one or two images the app gets crashed.
Any pointers on how to resolve this?
Thanks!!
720*1280*32 = 29491200 bits = 3.52 mb each one in memory.
Checkout this tutorial :)
Out of memory error means exactly what is stays. The application is trying to allocate to much memory. Android application are (depending on device) allowed to allocate 30-50MB.
The problem with the view pager is that it tries to hold at least 3 pages (current previous and next) to provide fluent UI work.
Bitmap to be displayed needs to uncompressed. So the only thing that matters is the size (pixel number) and color depth.
Usually 3 bitmaps of size you given should be quite easy hold on the device. I suppose that you are trying to process them in some not proper way, or you are missing releasing them from memory. Can't say more not knowing what are you doing with those bitmaps.
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