I´m working in an App which does have images that are used quite often, however there are others download used only once.
Does Glide have any way for deciding on the fly which images should be stored only in Disk or only in memory?
As far as I´ve seen it does the cache depends on the configuration buy I´de like to be able to say by myself which ones should be in disk and which ones no.
You can use .diskCacheStrategy() to manually control whether and how an individual request is cached on disk and skipMemoryCache() to control whether an individual request is cached in memory.
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.
My overall object is to delete certain type of images (which are temporary) after a certain period like after one month, from disk cache of the my app.
I'm using Glide, so I know that using Glide, I can clear entire disk Cache but my goal is to clear only a certain type of images from disk cache. Like for example, live banner images from my app (which keeps changing after certain period). Problem is, they keeps adding space even though one gets inactive. So ideally I should delete all old banner images from cache.
What I'm thinking is have a separate Glide Module just for these banner images and setup a different internal cache directory for these images, and after a month, ask Glide to delete/clear this directory.
Another thing is to use Glide's signature concept which invalidates the images.
For both of above ideas, my problem and question is that I want to use only for certain type of images but more I read about them, it feels like once I use them, they apply to all images being download using Glide
Even if I use multiple Glide module, they all gets used for all the images (that's why there is a concept of conflict management for glide modules)
I might be wrong, and there might be indeed a way to get a solution to my problem. All I need is your help if you know a way :)
I'm aware that if nothing works out for my solution, then to keep my app's size impact low, I'll have to decreased overall internal disk cache size which is 250MB by default.
Thanks.
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'm using Jake Wharton's DiskLruCache lib.
I'm curious about app performance, caching strategy, using caching both in a view and across a whole application. Most of the time, the image won't change.
Let's say for example I have a 320x320 photo on my server. I open the stream, save the image.
In my list views, I show bitmaps and in the detail, I show a larger image. Should I save a thumbnail bitmap too? Is that more efficient?
What is your experience with sharing the cache "object" across the entire app (let's say I have multiple views that might leverage the same data. What are the issues with this?
For the sake of performance and currency, what if the image changes on the server. What's the best strategy to know that it's changed? I don't have access to modified date. Only size and yet, I don't really want to query size every time either. Set a flag in the app on the server and then query the flag?
In a traditional application (if there is such a thing), what's the best practice for clearing the cache from time to time? (indent weirded out.)
(I was inspired to write this after seeing all of the performance improvements by Facebook in iOS. I don't have billions to do caching but I would like to at least be smart about it! LOL)
A lot of these answers depend on the type of app you're writing, how important image updates are (and how likely images will change, etc), and total images produced. Aside from disk caching, you should be using memory caching as well, especially in ListViews and other areas where the same images will be scrolled through repeatedly. Look at LruCache and read the Caching Bitmaps entry from Google.
320x320 is probably too big for a listview, you will likely want to create thumbnails (depending on device, and how you're implementing your listviews).
1) You should be using Disk caching fairly aggressively (how you define that is up to the app you're writing). Use the external storage directory, and if they have a few GB left over, it's not an issue if you take 100 mb for your app for instance. It can all be cleared away if it's ever needed anyway.
2) There shouldn't be an issue. Disk IO (even to a flash medium) should never be handled on the main thread. Use AsyncTasks to load the images. There can only be one main foreground activity at once anyway, and while an activity is sleeping, it shouldn't be trying to read from the disk anyway.
3) Again this depends on how you're implementing your app. You should be able to get additional information when retrieving the file (even Apache can tell your app the last modified date).
3.1) You can have a sqllite db that keeps track of how often certain images are used, and most recent read. If the most recent read is a few days old, let that image expire.
Edit: There's a library from Jake Wharton now called Picasso that I would recommend using, which handles the Network/local IO as well as memory and disk caching. Check it ou here: http://square.github.io/picasso/ . A lot of what you will need to do can be accomplished with one line: Picasso.with(this).load(imageFileURL).into(imageView);
I currently have my app caching image files in the cache sub-directory for the application. The images are used in a ListView and stored in a HashMap of SoftReferences to Bitmaps.
So my question is this, what is the best way to cache these image files without inflating the space my application uses AND remains responsive from a user standpoint.
Things I am concerned about:
I know the user can clear the cache and that it is done automatically when space is low on internal memory, but I feel most users will see a several MB app and uninstall it. Also if the space is constantly low, my app will just keep downloading the images, making it appear slower.
Most devices have an SD card pre-installed, but what should I do when it is not inserted? The SD card may also be slower compared to internal storage, affecting my app's performance.
Should I include an option to choose the location of the cache?
Should I attempt to manage the size of my cache (be it in the /cache or /sdcard) or just forget about it?
Thank you for your time (its a long one I know) and please post any relevant experience.
I can't offer you a comprehensive set of best practices, but I can offer what I've learned so far:
Managing your cache is a good idea. My app's cache is such that I know that I'll never need more than a certain number of cached files, so whenever I insert a new file into the cache, I delete the oldest files until I'm under the limit I have set. You could do something similar based on size, or simply age.
Caching to the SD card, if it's available, is a good idea if your cache needs to take up a lot of space. You'll need to manage that space just as carefully, since it won't automatically clear that space for you. If you're caching image files, be sure to put them in a directory that begins with a dot, like "/yourAppHere/.cache". This will keep the images from showing up in the gallery, which is really annoying.
Letting the user choose the location of the cache seems like overkill to me, but if your audience is very geeky, it might be appreciated.
I haven't noticed a much of a penalty when caching to the SD, but I don't know how your app uses that information.
Everyone has good ideas. I like the idea of using SoftReference's, although I'm not sure how often those get cleaned up, as this varies so much from VM to VM. You might want to combine that with regular HashMap to prevent you entire cache getting cleared every few minutes.
EclipseLink has a few different cache implementations and pretty good documentation on them. You could probably take advantage of a few ideas from the implementation (e.g., LRU, MRU, etc.). e.g.,
hard cache
soft cache
combined hard/soft cache
Since you're tuning a cache down to the nitty-gritty, I would recommend tuning it to different devices based on the hard specs. This is normally bad design, but the scope of the hardware that your software runs on mandates it, IMHO. e.g.,
Detect the amount of available memory on the SD card. Most new smart phones come with multi-GB SD cards, and those are pretty hard to fill up with regular usage for most users. Use away! You can also detect the amount of space available on the SD card on startup, and increase/decrease the size of your cache on startup.
Detect the amount of available memory and configure your caches with that in mind. If a user is using a hardware-intensive application, I don't think they'll mind that it makes up 200MB of RAM and provides a very fast user experience, especially since they spent a lot of money to have a phone that has 1-2GB RAM.
Good luck!
Should I include an option to choose the location of the cache?
IMO: No, let make it more simplest as possible (Except you can include advance setting for expert user)
Should I attempt to manage the size of my cache (be it in the /cache
or /sdcard) or just forget about it?
IMO: This is optional, it is double sword: your more work on background will help user more convenience but also more bug prone
Use 3rd libs:
IMO using 3rd library as Picasso is better, it handle cache automatically by order: Memory cache -> Disk cache -> Network