In android many image loading libraries (like Picasso -- which uses 2% of the storage for disk cache, Glide) use disk cache in addition to in memory lru cache. I can understand why this might be useful for images downloaded from the network -- if the in memory cache is full, read it from disk rather than fetching them remotely -- thus avoiding network latency etc. However, if we are just reading local images on the android device itself -- do we gain anything by using a separate disk cache with the serialized bitmap data -- since the data will have to be read from the disk anyways ? Probably makes sense if your app needs a thumbnail and subsample the original image once and store it in cache ? Are there any studies showing perf gains. I have seen use of disk cache in googles samples and other bitmap cache libraries.
so here are some refs I found in the AOSP docs:
A memory cache is useful in speeding up access to recently viewed
bitmaps, however you cannot rely on images being available in this
cache. Components like GridView with larger datasets can easily fill
up a memory cache. Your application could be interrupted by another
task like a phone call, and while in the background it might be killed
and the memory cache destroyed. Once the user resumes, your
application has to process each image again.
A disk cache can be used in these cases to persist processed bitmaps
and help decrease loading times where images are no longer available
in a memory cache. Of course, fetching images from disk is slower than
loading from memory and should be done in a background thread, as disk
read times can be unpredictable.
Related
I'm using vectordrawable for displaying images. The images are all resources which are bundled with the app (apk). My problem is, that the memory on every new activity massivly get higher until the app crashes with an OutOffMemoryException.
java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:903)
at android.graphics.Bitmap.createBitmap(Bitmap.java:880)
at android.graphics.Bitmap.createBitmap(Bitmap.java:847)
I've looked into MAT for memory leaks, but did'nt find out any more than the bitmap errors.
What are the efficients way to display vectordrawables? Maybe the general architecture of my app isnt right with the activity lifecycle?
I didn't find any informations about the common memory ussage of other apps (facebook, aibnb, whatsapp,..). My usage is around 40-70MB.
There are a few things to be careful about when dealing with images:
Are you loading your images every time when you show them? This can be a potentially very memory consuming operation. It's better to load the images into memory once and then reuse them across the app.
Are you cleaning the memory occupied by the images you no longer use? If you are sure that an image is no longer needed, you should clean the allocated bitmap memory by calling bitmap.recycle(). This invalidates the bitmap and frees all the occupied memory, making it available for other operations.
Are the images too large? There is a limit for the maximum size of a single image. Trying to load a bigger image will also cause an OutOfMemoryError, even though memory can be available. In that case, you may want to optimise the image files that you are trying to load.
Go though your app and check for those potential problems one by one. Also, there are good profiling tools available for the Android platform. They can show you potential problems with the memory management, like excessive memory allocation, etc.
Good luck.
One major issue with my application is crashing, which happens a lot due to the huge amount of content my app contains (it is a content-sharing site client). I get many memory errors, and I can be using up to 170-180 MB of ram, which is ridiculous.
http://i.gyazo.com/6cd53e6cf6f0a9bfdd6a24b323a70b09.gif http://gyazo.com/b64d50f76b2ef608954a6d6cdd5d52d0
Those screenshots are just from loading 25 submissions and scrolling through them.
My current setup is like so: LruCache with size of
(Runtime.getRuntime().maxMemory() / 1024) / 8
which handles all submission images. When I load a submission photo or thumbnail, it goes into that cache. Albums are handled by a simple ArrayAdapter and WeakHashMap store for bitmaps, because it is rarely called (maybe 1 out of every 25-30 posts contains an album). Gifs are streamed through GfyCat to a VideoView, no real crashes occur on gifs or albums. The real errors occur when I am scrolling, which is strange because I load the images into the LruCache all at once to save mobile radio time (battery improvements).
The issue seems to be that android is trying to possibly put more into the LruCache than it can, because I get errors like this
java.lang.OutOfMemoryError: Failed to allocate a 3169972 byte allocation with 1400991 free bytes and 1368KB until OOM
even though my LruCache size is 24576kb.
Am I handling memory correctly? What steps can I take to improve stability but keep the app speedy?
Thanks!
You can also even enhance the picasso further by use this configuration
Picasso.with(this)
.load(YOUR_URL)
.config(Bitmap.Config.RGB_565).fit()
.into((ImageView) findViewById(
R.id.frame_main_main_layout));
it will decrease allocating the memory and make the performance better
I ended up switching from the Ion image loading library to Picasso, and have saved 33% of ram usage with automatic caching, so I got rid of the LruCache and all my stores, now it's working better than ever!
I am using .cacheOnDisc() method for storing images in cache memory (Default method-Unlimited Extrenal Storage).should i enable cacheInMemory for my app?what r the effects will be if i dont use cacheInMemory option?
A memory cache caches the images in memory (RAM), i.e. it does not have to load and decode the image from internal storage because that is rather slow. You should IMO always use a memory cache.
The effect of not using memory cache can be - depending on implementation - that scrolling through lists of images is either stuttering or slower than necessary.
Disk (e.g. SD card) cache makes sense if the images are downloaded from the internets and you don't want to re-download them each time the app starts again. Local storage is much faster than the internets but still much slower than memory.
Until now I'm using a SoftReference Cache for images in Android. This cache is used for images that are shown in ListViews and should help holding images of items in memory that are not shown on the screen, if there is enough memory left.
The problem with this is that SoftReferences are garbage collected nearly at the very moment the last hard reference is released. The result of this is that an image that is removed from the screen is garbage collected at that moment and if the user scrolls back to this entry in the ListView the image is reloaded from the internal phone memory resulting in a complex lazy loading process, resulting in frequent redraws of the list and general bad performance.
The bug request for the soft reference behavior states that this is the intended behavior and that you should use a LRU-Cache for caching this kind of stuff.
Know to my question. The LRU cache will only take as much memory as I allow him to. But if the app needs a lot of memory it will not free memory. How should I determine how much memory I can allow the Cache to use, and is there a way to reduce the size of the cache if the memory situation of the phone becomes tight?
At the moment the image cache is saved inside the application as a kind of global image storage for all activities. This would result in my app constantly using all the memory of the image cache even if my activities are in the background or destroyed.
Keeping background processes alive is an OS-level optimization that makes switching back to your process fast. Your process will stay alive only as long as the OS can afford the memory; when that memory is needed for another application your process will be killed and its resources will be released.
If you free your cache each time your process is backgrounded, switching back to your application would no longer be fast because it would see cache-misses. This defeats Android's keep-background-processes-alive optimization!
You should just use the LruCache, which is also included in the Android Support Package for releases prior to Android 3.0 (Honeycomb).
I'm developing a small social networking app that makes use of something like profile pictures. Images are stored on a server and I have scripts set up that will send the image for each user to the app, which then displays it in an image view for each user, and then saves the image to external storage. The way I have it implemented now is that anytime the app needs the image after it downloads it from the server, the app will get the image from external storage unless a user has uploaded a new image (I thought this would be faster than redownloading it from the server every time). However, it seems to be taking longer to get the file from external storage than it does to get it from my server (and the server is pretty slow, running on wifi from 3 floors away...budget constrains :) ).
My question is what is the fastest way to get these images if the user hasn't uploaded a new one. Should I just downlaod it from the server everytime (I'm assuming not) or is there a better place in the filesystem to store the images that makes for faster retrieval?
Loading images from the SD card should be very fast. Some strategies:
Do it only once - Load the images into memory asynchronously when your activity or application starts. You don't want to be hitting the SD card every time your view updates.
Make them small - If you're having performance problems displaying thumbnails in a list, try saving your thumbnails as smaller images using inSampleSize to put less pressure on the decoder.
Use internal memory - I think that internal memory is faster, but it tends to be in short supply. You could certainly store some number of thumbnails in your cache directory to help speed up step 1.
Responsiveness over performance - The golden rule is to remember that absolute performance does not always correlate with responsiveness. Even if the images take a long time to load, choosing cleverly when to load the images can have a great impact on the user's perception of speed.