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.
Related
I want to save the images fetched from server for once and from next time i want to check first whether images are stored or not in device, if not then again it should fetch from server and store in user's device again, and if yes then application will use images directly rather than fetching from server again and again. It will be useful for enhancing the speed of application. Basically my application is fetching multiple images from server so i want to save those images on user's android device and from next time application should fetch from device. I think you got my question.
The simple way:
You can use Picasso.
It is a simple lib which provides image downloading and caching.
In my opinion it might not be the fastest, but it is pretty simple and intuitive. It does its job well and none who I asked complained about it.
Picasso
Other libs:
UIL
Volley
Glide
fresco
To make it short. There are lots of other libs. An awesome comparision of the most Populat ones can be found here and here
The do it yourself way:
You can also write you own caching logic with a LRUCache. Which is also pretty simple.
Take a look at:
https://developer.android.com/topic/performance/graphics/cache-bitmap.html
The LRUCache is just a Memory Cache so you might also want to use a DiskLRUCache
In the spirit of not reinventing the bicycle I'm wondering if there's an Android best practice approach (which I'm not finding through google, but I'm probably not articulating my search correctly) for keeping a defined amount of local storage allocated for downloaded bitmaps, which are kept around based on a most commonly utilized (rather than FILO or FIFO) algorithm.
So, what I'm going to be doing is grabbing an image if it's not already on the disk and storing it and marking it as "most recently needed". The next time it's used I'll be marking it as most recently needed again. Every time I do this I go through all the images and any image that has fallen beyond some threshold of recent utility will be deleted.
My algorithm also takes into account the reality that not all images are created equal and that there's a finite amount of space that I wish to allocate for image storage.
I'm not asking for "how to do this" (because I know how to do it)... I'm asking if there's already a prescribed approach that I should follow before I embark on my own custom implementation.
I think you need LruCahe. you can use UIL and all available caching mechanism or create your own with DiskLruCache. I think most of the libraries use LRU as an algorithm for caching images and I do not think any of them use LIFO or FIFO.
I can recommend the Picasso library for Android. Features as per site:
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use. Automatic
memory and disk caching.
I'm not 100% sure if this meets your requirements but it's worth to take a look at.
I am writing an android app which will have an image feed, something like in for example the instagram app. My question is how can I cache these images so i dont get an out of memory exception?
I have read some tutorials, but all of them are caching Bitmaps in LruCache. I might be wrong but as I think the bitmap in the ImageView and a cached one use the same ammount of memory.
I'm thinking about storing the compressed images (for example JPEG) in an in-memory cache (and of course on the disk) and showing it only when it is visible on the screen, but then the CPU will eat up the battery as it will constantly clearing the ImageView when it's not visible and decompressing the image and showing it when it is in the viewport. And I'm not really sure that the scrolling will be lagless, even if I do it on a new thread.
An alternative is to do the same as I described above, but I wont remove the bitmap from the imageview immediately, only when there are a lot of images and i will run out of memory.
What do you think?
Here is an example step-by-step on how to cache images, in memory and disk:
http://androidexample.com/Download_Images_From_Web_And_Lazy_Load_In_ListView_-_Android_Example/index.php?view=article_discription&aid=112&aaid=134
But you can also use libs that already work pretty well like :
http://square.github.io/picasso/
The first link also contains explanation on how you should treat bitmaps to avoid outOfMemory.
When my application connects to the server I check which icons are outdated or missing.
I store those icons in a sqllite database, the icons aren't very big, around between 5-10kb.
Everytime an activity starts, I'll go to the database and get the necessary icons.
But many of my activities use the same icons, so I was thinking about getting them from the database once, and then cache them somewhere to speed up my application.
How should I do this ?
I was reading this link: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html and they mentioned an lruCache for bitmaps.
But isn't this a bit of overkill for what I'm trying to achieve?
Absolutely no.
The LruCache is the proper approach to cache stuff, it doesn't matter the size of the images.
Remember to create the cache as a singleton element to be accessed equally by any element on your whole application.
DO NOT USE WeakReference as some people will suggest. They do not work very well on the Android, if you're in a search mood you can check the Google IO 2012 talks on YouTube that the Android team themselves are explaining why not use WeakReference and how to properly use LruCache.
edit
found the youtube link
http://www.youtube.com/watch?v=gbQb1PVjfqM&feature=plcp
Your question does not sound like you are asking how to do a memory cache, but whether it's reasonable to do it at all. Does the application already feel like the icon loading is a bottleneck? What else is your application doing? Some networking perhaps? How many activities (out of all activities) actually do have some icons? How many icons per activity do you have? How many icons is there in total? Guessing from #Budius post, doing memory cache right is not completely straightforward issue on Android, so make sure that you are not doing an unjustified premature optimization
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);