I have a photo gallery(list) in my app, and I use the Picasso library to display images.
But while using the app, the app crashed sometimes because of the Out of memory error. And after searching a web, I found the solution which is to disable using cache for Picasso library.
.memoryPolicy(MemoryPolicy.NO_STORE, MemoryPolicy.NO_CACHE)
After disabled using cache, the error is gone, but I think there is some smart way to using the cache.
Is there any guild line for using Picasso cache? like if the memory usage is closing to limit then, disable the using cache?
As I know, the Out of memory means that the application's memory limit is reached, maybe you try to load a really big image, or the memory for your app is not enough.
Maybe the top answer in this question can help you Simple Android App - Out of Memory error when running on smartphone
Related
I am new to Android development. My app has use case where I want to download and display images from Internet. I am using Kotlin to build App and decided to use Coil library as Image loading library. While using my application, user's action my trigger download of multiple images. How do these image loading libraries make sure that memory/cache/disk space doesn't fill up? Do these libraries clear/delete images that were downloaded during last use?
The answer is going to depend on the particular library. But in general, they download the images to a file, to serve as a disk cache. That disk cache generally is kept to some limit in terms of size, with files being deleted on an LRU (least recently used) basis. They may then do the same with in memory representations, keeping the last N megabytes worth of images cached in a pool, ejecting on an LRU basis when needed. Ejecting them from the cache may or may not remove them from memory entirely- it depends on if any other reference to the object is maintained by client code. Some libraries allow configurable behavior on this, by either allowing client code to set size limits or provide entire cache implementations.
It's still possible for space to fill up. Especially memory- if you have too many bitmaps open and use up all available heap, then you're going OOM no matter what the loading library does. What the loading library will do is prevent multiple network requests for the same image, and prevent you from having to do all the cache management by hand.
I have this aplication thats keeps building cache every time I open the app
In my app I load like 20 images from my website, but I don't save them to cache,
does the app automatically save this images to cache? If so, I don't think they load from cache, cuz I still have to have internet to load them
Admob in the other hand, if I don't have internet and I loaded the test ad before, it will load the testad.
currently I have the app to delete the cache everytime it starts, keeping cache low, but this doesn't seems smart.
My questions are:
Does admob uses cache of my app?
Knowing my app loads 20 images from my website, this images being
loaded affects my cache size even if I don't save them
programmatically to cache ?
is deleting cache expensive enough to have a dedicated thread to
do just that?
Does admob uses cache of my app?
Yes i think Admob caches its ads so they load faster. And Admob should be managing its own cache size. I don't think you need to worry about that.
Knowing my app loads 20 images from my website, this images being loaded affects my cache size even if I don't save them
programmatically to cache ?
No images or bitmaps will not be cached unless you do so, see this link for more info. I will recommend that you use the Glide or Picasso for image loading since they are memory efficient and abstract out most of the complexity.
Is deleting cache expensive enough to have a dedicated thread to do just that?
I don't think you should use dedicated thread. What you can do is override onTrimMemory and keep monitoring the memory level.When your memory level is critical or low you can delete the cache. Check this link for more info. In my opinion if you use Glide for loading your images it will already handle the memory very well and prevents OutOfMemoryError. Also, loads image much faster.
I am trying to figure out the best and the most efficient way of caching images to the disk, such that they would persist even after app is killed and re-launched in airplane mode. Consider the following use case:
Open the app and get all images and display them in their respective ImageView's
Kill the app
Put device in air plane mode
Open the app again.
I am trying to get the images to persist in an offline cache so that they can be displayed in the scenario mentioned above.
I went through documentation for picasso and glide and it wasn't exactly clear if their disk caching would work in this case.
Is there a way to do this using picasso or glide? I am trying to avoid having to write a custom implementation for storing this in SQLite etc.
Glide will do this for you by default without any extra work on your side. You can also customize what versions of the requested image to store in the cache.
One important thing you need to consider is if the URLs that you use Glide to fetch images from are available offline otherwise you will need to have some way to cache those as well so that you can initiate the Glide calls when you are offline.
You can see how I did it in this project: https://github.com/KhalafMH/popular-movies-android.git
To read about how to configure Glide caching see:
http://bumptech.github.io/glide/doc/caching.html
Currently, I am using a WeakHashMap to store my BitMap and link it to my key, but I have noticed it begins to use a ton of RAM. Is there a better solution to caching the BitMaps till I need them? It is unlikely I will need the image after the application closes, so a long-term solution isn't really needed.
Thanks!
I need to keep them in memory in case the user swipes back to a
previous view to save bandwidth and make the ViewPager more responsive
FragmentStateAdapter is meant for precisely that. Also use setOffscreenPageLimit() and setRetainInstance() in conjunction with that.
Storing Bitmap objects in runtime memory is not a good idea and will sooner or later lead to OutOfMemoryErrors getting thrown.
It is unlikely I will need the image after the application closes, so a long-term solution isn't really needed.
Storing images in cache wont be a problem as system doesn't clear image from cache even after you close the application or unless you clear the app data from setting.
For image downloading you can use image libraries like:
Image loaders:
https://github.com/nostra13/Android-Universal-Image-Loader
It gives you option to save image in cache.
You can also use volley library. But in this you have to implement your own code for cache storing.
http://developer.android.com/training/volley/index.html
Otherwise you can also implement your own code for cache in which you can use memory disk for caching.
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#disk-cache
Use an LruCache. There are plenty of online guides on the developer site.
I am making an attempt to build the most efficient way of caching images downloaded from the web for my app, a few years ago I tried to do this and could not find an efficient method of making this work until I stumbled upon the lazylist adapter found here:
Lazy load of images in ListView
this worked well until android 4.0 was introduced, at this point the app would crash after loading 10 to 20 images, as opposed to before where I could simply load up as many as I wanted without any issues, this I later found out was a result of the Ice cream sandwich having a set limit on memory usage per app, which didnt exist in Gingerbread 2.3 and below, I eventually decided to just clear the cache every 10 or so images to avoid crashing, however the user experience wasn't very good as a result of doing this and the app used tons of data as it was constantly redownloading images over and over again that were already viewed, I have since attempted to use an lru cache but this does not seem to work at all, especially when I leave the app and relaunch it the images are all released it seems, I need a better way of doing this and I have noticed that other apps such as instagram seem to have found a way to cache hundreds of megabytes of images, Im consistently having to manually clear the instagram cache in my settings because it seems that they are to able to store an infinite sized cache that seeming never ejects its contents, does anyone know how to build this kind of cache?
You can try using https://github.com/nostra13/Android-Universal-Image-Loader
library. This does most of the hardwork for you.
the way I wold suggest would be to store the images from the web to the sdcard or something then store the URI where the mage is located. The in your list just load the image from the uri.
If your images are big in size you should probably rezise the image before you save it so that you use less memory and it will load faster since the processing has already been done
BTW the memory limit always existed in android