Displaying lots of images without storing them as byte data? - android

Ive been using various lazy loading techniques for images and other things. It works but I was wondering if there is a better way that some one knows of for getting an image from a server/webservice/whatever that doesnt require as much memory or time to download. The reason I ask is because I have an overseas developer asking me to rebuild a webservice for a project and hes asking me to allow them to just use a url to get the image. My thought was that whether its a url or a post to a service the result still has to come back via an inputstream which is going to take up the same memory whether virtual or stored in hard storage. His question had me slightly confused so out of curiosity Im asking on here......is there a way to get an image without using an inputstream? I guess it would be like a calorie free image lol.

You can blit the big image into a small image and discard the big one. This is how thumbnails work in image programs.

Related

Android best way of caching images

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

Idea to download images in android

I'm making an android app, here the images are getting from Cloud, is it good idea to download images and save it & use it further. Or download images every-time user uses the app, what idea you prefer is the best?
Because downloading images always is slow & its bad i know but at some point if the images are updated then how to get to know about it?
You should definitely cache your downloaded files!
Do it in your internal app directory where only you do have access to (or otherwise external storage, thats still ok).
Bandwidth and connections are always expensive and should kept low as much as possible.
So your user can see images fast even on a bad connection and your app doesn't waste his valuable bandwidth of a users data plan.
Maybe this could also help you:
https://github.com/novoda/ImageLoader
http://www.androidhive.info/2012/07/android-loading-image-from-url-http/
Make it easy on yourself and use something like Android Smart Image View. It takes care of loading and caching, and it's just about a drop-in replacement for Android's ImageView. Universal Image Loader is another alternative, more configurable, but not as quick to implement.
I used https://github.com/nostra13/Android-Universal-Image-Loader
but I think you not want only download and cache.
these no trick ,if you want check weather the image update or not, you can add metadata for image, just like md5 .
in html and browser, you can set expires header for a image:
enter link description here
but in android app, you control all yourself.
Downloading images and saving them is probably the best way to do it because you don't want to download the same images over and over. If the images are updated you can delete the older one and download the new ones. Just make sure you don't download/save a million images. Take a look at this library. It has a built-in cache on sdcard/external sd.
Downloading images from the net for display, with possible requirement of caching is a very common problem that many people have solved, you can try these solutions to see which fits you:
Ion (https://github.com/koush/ion) - very flexible and feature complete, plus it can download more than images but JSON, Strings, Files, and Java types as well. The part that I really like about this is that it can automatically cancel operations when the calling Activity finishes, so users don't waste time & bandwidth downloading images that will no longer be displayed
Universal Image Loader (https://github.com/nostra13/Android-Universal-Image-Loader) - equally capable for most use cases but for downloading/caching images only

removing image data from memory

I have to believe there's a way to clear image data from memory once it's no longer required, but despite exhaustive searching I can't find a solution. Both stack and the google android dev list are full of questions regarding OOM errors, specifically "bitmap size exceeds VM budget", but I still don't see a clear answer.
I understand there are hard memory limits on devices, and I understand it's not realistic to load up and display or cache large amounts of image data, but there should be away to discard data that's no longer required.
For example, imagine this very basic hypothetical app, that emulates a lot of the behavior of the native gallery app:
An image gallery that allows the user to peruse images from a remote server.
There might be any number of images on that server.
The app displays 1 image at a time, and allows a user to go back or forward 1 image at a time through button presses or swiping.
There'd be a maximum of 3 images rendered at any one time (so the user can see the one immediately to the left or right of the current image when swiping). All other image data should be discarded.
Images are loaded using URL.openStream and Drawable.createFromStream or BitmapFactory.decodeStream. Streams are closed appropriately.
Images are sized appropriately on the server before being fetched.
Loading happens in AsyncTasks. Tasks that are no longer needed (due to moving away from an image with an incomplete task) are cancelled. Any references in the AyncTask are WeaklyReferenced.
When any image is no longer required, it's "cleared" via:
getBackground().setCallback(null)
Listeners are set to null
setImageDrawable/Bitmap(null)
removeView
This simple construct, that takes into account all the suggest practices I'm aware of, will inevitably crash with an OOM error at some point. Using BitmapFactory.Options inSampleSize and inPreferredConfig will delay the inevitable, but not forever, and at the cost of image quality. In this example, I've used remote images, but the issue exists with images stored in /assets/ or in internal memory, etc.
My feeling is that if we can display X amount of image data at one point, and we take all steps to remove that image data from memory, we should be able to display that same amount of data later, without having to compensate for what has happened before.
With the sheer quantity of questions about this very issue, I'd hope to have a standard solution documented, but if there is one, I can't find it. I've seen answers posted by Romain Guy, who otherwise seems very generous with his knowledge and active in the community, that say something like "Simple. Don't use so much memory". OK. Tell me how.
I should also mention that System.gc does nothing to help this. I'm also aware of bitmap.recycle, but unless I'm mistaken this can't be used in this fashion.
Am I missing something fundamental? Is there a way to discard image data once it's no longer being used? What is missing from the above to create a simple photo gallery? Assuming the built-in gallery app uses the framework and not the NDK, I imagine there has to be a way...
TYIA.
/this question has also been posted on the android developer google group list.
Through my work with Prime I found a few tips, one of which you have not mentioned. When you decode your Bitmaps make sure to use the inPurgeable and inInputShareable flags in your BitmapFactory.Options. That will help a little bit but I would recommend you look at my implementation of image loading in Prime. I use it in all of my products without any memory issues. I have found that 95% of memory problems are from the incorrect usage of the Bitmap class.
There is a very detailed article about the use of bitmaps on the android developer website.
Did you look at it ?
It explains how to load, cache and display bitmaps efficently and how to get rid of this famous OutofMemoryError.
There is also a sample application from an image gallery.
I think that's what you're looking for.

Memory efficient way to scale an image

I've got an app where the main viewing area is a WebView.
It's a service where a user can also upload a photo. However, with the WebView, and photo uploads, I'm getting some OutOfMemoryErrors.
Usually all it takes is a page loaded in the WebView, and then simply trying to open an image with something like this:
Bitmap bmp = BitmapFactory.decodeFile(path);
The only reason I need to open the file at all is so that I can scale it down so that it fits in a max width/max height dimensions before uploading it.
I've even tried opening it in a sampled fashion, similar to what's mentioned here:
Strange out of memory issue while loading an image to a Bitmap object
However, with a complex webpage loaded in the WebView, I still get OutOfMemoryError when trying to open the image.
Is there a way to scale it, maybe using another process or something, that's more memory efficient?
I'm glad you asked, I was about to investigate this for my own project.
It looks like BitmapFactory.Options is your friend here, specifically BitmapFactory.Options.inSampleSize enter link description here. You can use BitmapFactory.decodeStream to get the image dimensions without creating a Bitmap.
Googling revealed the com.bristle.javalib.awt ImgUtil classes; these appear to be open source (don't know the license), and are AWT based, so may work on Android. The interesting method is ImgUtil.scalueImageToOutputStreamAsJPEG, which works with InputSteam/OutputStream, so may be memory efficient.
UPDATE
An alternative is to write a JNI wrapper around /system/lib/libjpeg.so, which appears to be standard on Android devices. This library works with scanlines, so can be memory friendly. Another plus is that using JNI should be faster than pure java.
Hope this helps,
Phil Lello
I had a similar problem and found a workable solution using BitmapFactory.Option.inScale. You can find details here: How do I scale a streaming bitmap in-place without reading the whole image first?

android loading and saving images on the device

I am building the application that will load list of news from the website. Each news/headline has an image. I want to save/cash the images so user does not has to download them again.
Q: In your opinion, what would be a better/more sufficient way: Loading images and saving them on the device or use the CacheManager? At the moment I am using the first solution and everything works fine. However, the website has many categories and even more news per category therefore there are lot of images saved on the device. Is it normal in this type of applications to save the images on the device?
Thanks for your help,
marqs
I don't think you should save the images on the device, because of many reasons:
Why wasting the device space on news images? All the user wants is to read the news and thats it. (In your case maybe open it later, but still - not forever)
You can save it on the device and make the app. delete those files after lets say 24 hours..
The main issue is the privacy issue, when the user is deleting the cache files he thinks all the webs he visited has wiped from the device, but in this case they aren't..
Maybe you can just add a "Clean Cache" button in the app. but after all I wrote I think using the Cache-manager is the best way - just because it was meant for those things exactly..
:)
Rotem
I didn't find a reason to use CacheManager. I used getCacheDir and stored everything on file. I have two levels of cache. First when I fetch it, I store in memory and disk. When in memory gets bigger than 30 objects, I started clearing the memory to make some room for the new images coming. However, I still keep the images around on disk and bring in to memory as needed. I found this to give me the smoothest scrolling. After about an hour, I start expiring the image on disk too.

Categories

Resources