views:

3106

answers:

4

how to cache images after they are downloaded from web

+7  A: 

Convert them into Bitmaps and then either store them in a Collection(HashMap,List etc.) or you can write them on the SDcard.

When storing them in application space using the first approach, you might want to wrap them around a java.lang.ref.SoftReference specifically if their numbers is large (so that they are garbage collected during crisis). This could ensue a Reload though.

HashMap<String,SoftReference<Bitmap>> imageCache =
     new HashMap<String,SoftReference<Bitmap>>();

writing them on SDcard will not require a Reload; just a user-permission.

Samuh
how can we write image on sd or phone memory?
Faisal khan
To save images on SD card: You can either commit the Image Streams read from the remote server to memory using normal File I/O operations or if you have converted your images into Bitmap objects you can use Bitmap.compress() method.
Samuh
+5  A: 

To download an image and save to the memory card you can do it like this.

//First create a new URL object 
URL url = new URL("http://www.google.co.uk/logos/holiday09_2.gif")

//Next create a file, the example below will save to the SDCARD using JPEG format
File file = new File("/sdcard/example.jpg");

//Next create a Bitmap object and download the image to bitmap
Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());

//Finally compress the bitmap, saving to the file previously created
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));

Don't forget to add the Internet permission to your manifest:

<uses-permission android:name="android.permission.INTERNET" />
Laurence Dawson
Why are you decoding the JPEG and then re-encoding it? You are better served downloading the URL to a byte array, then using that byte array to create your Bitmap and write out to a File. Every time you decode and re-encode a JPEG, the image quality gets worse.
CommonsWare
Fair point, was more for speed then anything. Although, if saved as a byte array and the source file was not a JPEG wouldn't the file need to be converted anyways? "decodeByteArray" from the SDK Returns "The decoded bitmap, or null if the image data could not be decoded" so this makes me think its always decoding the image data so would this not need re-encoding again?
Laurence Dawson
Speaking of efficiency, wouldn't it be efficient if instead of passing FileOutputStream we pass BufferedOutputStream?
Samuh
+3  A: 

I would consider using droidfu's image cache. It implements both an in-memory and disk-based image cache. You also get a WebImageView that takes advantage of the ImageCache library.

Here is the ImageCache library code specifically:

http://github.com/kaeppler/droid-fu/blob/master/src/main/java/com/github/droidfu/imageloader/ImageCache.java

Here is the full description of droidfu and WebImageView: http://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadapter/

esilver
+3  A: 

And now the punchline: use the system cache.

URL url = new URL(strUrl);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (result instanceof Bitmap) {
  Bitmap bitmap = (Bitmap)response;
} 

Provides both memory and flash-rom cache, shared with the browser.

grr. I wish somebody had told ME that before i wrote my own cache manager.

edrowland
Wow, this was an incredibly elegant way to do this, thanks a lot. It is in no way slower than my own simple cache manager, and now I don't need to do housekeeping on a SD card folder.
kread