Caching bitmaps - Android - android

I have a ListView where each cell contains a bitmap that is downloaded from the internet. To avoid out of memory errors I was wondering what the best way is to deal with this.
I have looked at softreferences for the bitmaps but I was wondering what happens if I am in the current activity and the the application begins to run out of memory. How does it decide what bitmaps to recycle?
Is a better way to write the file to disk and load it into memory when I need it? Are there any examples?
Thanks

I dealt with that a while ago. Experimented with performance too. Here's what I got.
This answer is beyond lazy loading of images because it deals with performance.
First of all: Forget about SoftReferences on android. Very bad for caching because of misbehavior (released to soon). I ended up using LruCache (source for API < 12) with a fixed byte size for the cache.
When loading images through network you want to persist the loaded images (in private app data folder or SD card). Otherwise the user is forced to load (unnecessary) data on every app startup. Here's the routine:
image is requested
check for image in memory cache (jump to 6. if available)
is persisted locally (jump to 5. if so)
load from network and persist
load bitmap into cache
load bitmap from cache into view
Now some words for performance. If every list item has another image and they have a fixed size (e.g. 40 x 40 dip) you would waste cache memory when loading full images (e.g. 800 x 600 px) and your device would have to calculate a lot for scaling.
First solution is to prescale the bitmap on step 5. before loading image into cache. You'll get the best performance when you persist the scaled image and load it next time.
You can find an example in my CoverCache helper (CD covers - but can be used for any kind of image data). It deals with persisting, scaling and caching images at the same time.

There is a lot of implementation of a list view with lazy loading of images with reuse of the views via the convertView mecanism. For example, take a look here : Lazy load of images in ListView
There are quite a few solutions there.

Related

How to reduce memory usage of image in Android

I have a screen where I have to show two similar images on screen . The size of both these images is dynamic but they covers most of the screen. When I navigate to this screen in my app, I see a spike of 12MB in Memory Monitor in AndroidStudio meaning both these images is using that 12MB as there is no other UI element on that screen and as both these images are similar takes takes equal amount of screen space, I guess each consumes 6MB of memory when shown. The dimensions of both these images are 1174 x 1174 pixels and the size is 396KB in res directory.
I have tried using Glide but I see same memory spike when these images are loaded through Glide too. Even Glide can't help if the app tries to take more memory than available and there is heavy usage of images in other parts of my app. So there is always memory crunch and I'm getting lot of OutOfMemory exceptions in the app where these two images are shown.
So my question is how can I reduce the memory usage of those images? Also why does the image takes 6MB of memory when it's size is 396KB in res folder?
I am guessing you did not compress your images, use https://github.com/zetbaitsu/Compressor very great at image compression. Also i am also guessing you did use Glide caching strategies.
Glide, however, caches the original, full-resolution image and additionally smaller versions of that image. For example, if you request an image with 1000x1000 pixels, and your ImageView is 500x500 pixels, Glide will put both versions of the image in the cache.
DiskCacheStrategy.NONE caches nothing, as discussed
DiskCacheStrategy.SOURCE caches only the original full-resolution image. In our example above that would be the 1000x1000 pixel one
DiskCacheStrategy.RESULT caches only the final image, after reducing
the resolution (and possibly transformations) (default behavior)
DiskCacheStrategy.ALL caches all versions of the image
To answer your answer you need to manually keep track of the cache volume in android.Try forcing an garbage collection,Normally, VMs perform garbage collection only when absolutely needed, since it’s expensive. However, it can be useful to force garbage collection in certain circumstances. For example, when locating memory leaks, if you want to determine whether a large object was successfully released already, you can initiate garbage collection much more aggressively than usual.
Hope this was helpful.

Android Image Gallery Memory Use Theory

So, I've been researching on bitmap scaling using the bitmap factory.
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
I'm doing so because the application I'm working on requires a gallery that allows users to submit their photos to be added to the gallery. These photos will then be read from a URL.
My theoretical problem is this: Considering the android devices can have as low as 16MB of memory, even scaling down the images is only delaying the inevitable unless only handling a single image. Whereas in my case, the amount of images that will be loaded could be hundreds. Meaning that even if they're scaled down, eventually one will reach that limit.
My only idea thus far are to load one image at a time, which is not preferable since users will have to wait between photo transitions.
That being said, is there anyone who has experience developing applications on android that handle 100's of images? If so, is there any theory you could share on handling all these images fluidly? It can obviously be done, as there are gallery applications available. I am just unsure how they accomplished it given the restraints.
Please note this is not a request on how to use the bitmap factory to scale images, as that question has been answered many times.
Rather a request on handling data amounts you know will exceed limitations.
The gallary apps should not be storing all thousands of images in memory. Use the Viewholder pattern such that the image views displayed will get recycled (this is forced upon you if you use RecyclerView). On backend use an image cache and keep a limit on it size.
See e.g. What is the benefit of ViewHolder? and How to release memory of bitmap using imageloader in android?
The Android gallary app source may be a good reference: https://android.googlesource.com/platform/packages/apps/Gallery/+/android-5.1.1_r18/src/com/android/camera

Out of memory error while loading hundred of bitmap images in Scroll view in android

I am Working with one android tablet application in which lots of work with Images.
i have to load hundred of large bitmap images in scroll view. one image is around 1Mb to 3 Mb.
i have already scale images using bitmap factory and sample size, and also load all the images in Async task.
i am loading all the images from SD card.
Still facing OUT OF MEMORY issue after scrolling some images.
any help would be appreciated.
thanks in advance.
hi hope your solution.
you can user Univarsal Image Loader. This is better api for image download and store in catch. and get from catch. it's a great api for image operation.
this case is often come while we getting bitmap so just use lazy loading. just take a look on this example
http://sunil-android.blogspot.in/2013/09/lazy-loading-image-download-from.html
To prevent your application from soaking up CPU time without getting anything done, the JVM throws this Error so that you have a chance of diagnosing the problem.
Its because of large bitmap memory in stored in native area
so it better i suggest you use libraries like Universal Image Loader or
Bitmap Fun from android
You have to find out when the OOM error occurs. Is it when you have too much bitmap cache in memory without releasing or you just meet it when you're decoding certain bitmap?
For the first situation, I think you should manage your bitmap cache yourself or using some effective 3rd-party library which mentions above.
For the second situation, I've met it on some low-performance mobile(usually with 512MB or less memory), when you decode a bitmap to requested size, it may needs a rather large memory to store the bitmap, for 240dpi devices, it's about 800 * 480 * 4 = 1.5MB, however you may fail to allocate that much memory on some machines cause they may have strict memory manage strategy to prevent that much memory allocation. You should just catch the OOM error and continue rather than get a crush.
Loading a bitmap in 1280x800 display will take 1280x800x4 byte (~4MB) memory. Java heap size is limited (~50MB) so you can not use lots of large bitmaps in your app. Using cache and reusing bitmap objects are necessary while working with bitmaps but another useful trick is to use larger hip size! to do so, add android:largeHeap="true" to Application tag in your manifest. It increases hip size to 4 or 5 times larger (~250MB) than normal. I hope this help other people reaching this thread while they search!

Out Of Memory Error Using Bitmaps in Drawable

I am working on a wallpaper app. I have all my images stored in Drawable folder.
I am getting OutOfMemoryError when I add more than 30 wallpapers. I want to know how to overcome this.
Should I save all my images in SQLite Database and then load from there or should I have to do something else.
I have tried resizing bitmaps through Decode Bitmap Factory but it did not serve my purpose as the quality of images is reduced.
Resizing images at decode-time will only move your OutOfMemoryError ahead in time. That error means that your application leaked memory, or tried to use more memory than the available one. When working on bitmaps on Android, this happens quite often, because the limit is set around 25MB, and high resolution screens are increasingly common.
You have to redesign your application. There's no need to keep 30 images in memory, because they can't fit in a single screen - well, if they are thumbnail-size, you resize them all when you decode, and the total number of pixels in memory is the same as a single big picture, so you don't run out of memory.
You have to find a way to recycle() bitmaps when they are not visible. If you better describe your application, we can help you find the appropriate moment, also to preload images to have a responsive application and a better user experience.
I think what you need to do is display Thumbnails instead of drawable image on your screen. You can generate Thumbnails and display as per your size requirements. And whenever user click on Thumb, just take original path and set wallpaper.
Another option is you can use Universal Image Loader which helps you to buffer your image in disc (like SD card or your application's Internal memory). So issue of Out of Memory can be resolved.
If you want to control the crash of your Application then write your code in Exception block:
try {
...
}
catch(OutOfMemoryError error) {
//decide what to do when there is not more memory available
}
Also please the this link:
link

Many and Large image loading in Android

I have a problem: (I wouldn't be here otherwise ;)
I am creating an app that has a feature for displaying "3D" models. This part is really a collection of images taken from many angles and allows the user to "rotate" the "model".
This idea is working fine, but the problem lie in the loading of the images.
I have found that there are two ways:
Load all the images into memory, and then simply switch them for the correct angle.
Load the images as we need them - we can load a few ahead of time.
However these have problems:
If I was lucky, the images would fit into memory, but they don't. They are about 1.5-2MB each and there are about 75-100 images per model. This brings the total size to about 115MB at the minimum.
If I was lucky, the image would load quicker than the user could "rotate", but they don't. The user can easily switch to an angle that is not loaded yet, resulting in a black screen for a few seconds.
I have created a loader that allows me to simply add the images that I need to a stack and the loader will then one-by-one load the images. This works fine if the user scrolls fairly slowly. My loader takes care of releasing memory when it is finished, so no matter how many images I load, the app usually won't crash as long as I specify the max images to store in memory. My loader can load the images very quickly, but there is still a few milliseconds (~250ms) for it to load the large image into memory.
Of course, the loader is on a different thread, and the loading in no way hinders UI response. That is why if the user swipes back and forth quickly, no image will actually display, as the loading and unloading are all working at the same time to result in no images :)
So, my problem: How do I provide a smooth and user-pleasing rotation of the images without loading all the images into memory?
Don't load (or store) resolution you don't need. If your user needs to zoom, an out-of-memory binary image pyramid is a cheap way to let you load only the level of zoom necessary. If your user needs to pan through an image larger than your display area, you can break your large image into smaller tiles, and only load the ones you need.
If you want to get fancy, you can write a UI-aware cache manager to preemptively load tiles you think you might need soon, and mark tiles you're pretty sure you won't need soon for preemption.
Better compression can fit more image data into memory, and speed up load time. So, pay attention to individual image compression, and don't load image quality you don't need, either.
As an extraordinary measure: since images from slightly different angles are similar to each other, you may be able to save time and space by representing the difference, instead -- look up lightfield compression. You will still need to convert from compressed form to a particular bitmap you can draw, but if the compression allows the dataset to remain in memory, you could potentially gain a lot of speed.
If you can't fit your compressed dataset into memory, there's a good chance the user will be able to swipe back and forth quickly enough to defeat your cache. So, if smoothness is your main goal, you could try for a "UI solution" by restricting the rotation rate (or the per-swipe rotation range?) to something your data loader can follow.
My only suggestion is for loading them efficiently. I assume that you are using techniques described here
If the images are of higher resolution than the screen you can calculate the sample size of the image you want to render then you can load an image that fits your screen rather than the full size image which will use much less memory. If you are already doing that then to me it seems like how you are doing it efficiently already. Perhaps you could show the user some kind of placeholder graphic while an image is loading so they won't just have blank space.
Thanks for the answers. I laughed at myself and then went to bed after reading the answers.
Let me share how I resolved this problem - it uses some pieces of the answers:
I was trying to cache the large images in memory - this is unnecessary, why not store a lower res version and then load the hi res when the user stops scrolling? Then the user can scroll as fast as he likes and there will always be images in memory to quickly paint. When the user stops/slows scrolling, we load the hi res image.
Because he will be scrolling fast, he won't be able to see the lower res' lower quality.
And, as there will only be one hi res to load, the ~250ms delay is hardly noticeable.
This really combines the best of both cases. And I can use the Android's methods for loading a lower res version of the Bitmap.

Categories

Resources