Tutorial details

Android – Load images from web and caching | App Code for Sale | Preview

Android – Load images from web and caching | Android Tutorial

How to check and load image from local if cached already

Overview PAGE TOP

Have you gone through my previous article for Loading Remote Images in android?, actually it was the solution for loading images from web but not caching into the local storage so that it has to load image every times, instead here in this article i am going to show you code/demo for loading images from web as well as to cache images in local also, so that whenever image has to be loaded it will check and load image from local if cached already.

android_image_loading_device-171x300.png

MainActivity.java PAGE TOP

view source

print?

01  package com.technotalkative.loadwebimage;
02   
03  import com.technotalkative.loadwebimage.R;
04  import com.technotalkative.loadwebimage.imageutils.ImageLoader;
05   
06  import android.app.Activity;
07  import android.os.Bundle;
08  import android.view.View;
09  import android.widget.ImageView;
10   
11  public class MainActivity extends Activity {
12   
13   private ImageView imgView;
14   private ImageLoader imgLoader;
15   private String strURL = "http://technotalkative.com/android.jpg";
16    
17      @Override
18      public void onCreate(Bundle savedInstanceState) {
19          super.onCreate(savedInstanceState);
20          setContentView(R.layout.activity_main);
21           
22       imgView = (ImageView) findViewById(R.id.imageView1);
23       imgLoader = new ImageLoader(this);
24      }
25    
26      public void btnLoadImageClick(View v){
27        
28       imgLoader.DisplayImage(strURL, imgView);
29      }
30  }

ImageLoader.java PAGE TOP

Using DisplayImage(Url, ImageView) method of ImageLoader class, you can load and cache image. You just need to provide the web url of image and the imageview in which you want to display loaded image.

view source

print?

001 package com.technotalkative.loadwebimage.imageutils;
002  
003 import java.io.File;
004 import java.io.FileInputStream;
005 import java.io.FileNotFoundException;
006 import java.io.FileOutputStream;
007 import java.io.InputStream;
008 import java.io.OutputStream;
009 import java.net.HttpURLConnection;
010 import java.net.URL;
011 import java.util.Collections;
012 import java.util.Map;
013 import java.util.WeakHashMap;
014 import java.util.concurrent.ExecutorService;
015 import java.util.concurrent.Executors;
016  
017 import android.app.Activity;
018 import android.content.Context;
019 import android.graphics.Bitmap;
020 import android.graphics.BitmapFactory;
021 import android.widget.ImageView;
022  
023 import com.technotalkative.loadwebimage.R;
024  
025 public class ImageLoader {
026      
027     MemoryCache memoryCache=new MemoryCache();
028     FileCache fileCache;
029     private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
030     ExecutorService executorService;
031      
032     public ImageLoader(Context context){
033         fileCache=new FileCache(context);
034         executorService=Executors.newFixedThreadPool(5);
035     }
036      
037     final int stub_id=R.drawable.ic_launcher;
038     public void DisplayImage(String url, ImageView imageView)
039     {
040         imageViews.put(imageView, url);
041         Bitmap bitmap=memoryCache.get(url);
042         if(bitmap!=null)
043             imageView.setImageBitmap(bitmap);
044         else
045         {
046             queuePhoto(url, imageView);
047             imageView.setImageResource(stub_id);
048         }
049     }
050          
051     private void queuePhoto(String url, ImageView imageView)
052     {
053         PhotoToLoad p=new PhotoToLoad(url, imageView);
054         executorService.submit(new PhotosLoader(p));
055     }
056      
057     private Bitmap getBitmap(String url)
058     {
059         File f=fileCache.getFile(url);
060          
061         //from SD cache
062         Bitmap b = decodeFile(f);
063         if(b!=null)
064             return b;
065          
066         //from web
067         try {
068             Bitmap bitmap=null;
069             URL imageUrl = new URL(url);
070             HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
071             conn.setConnectTimeout(30000);
072             conn.setReadTimeout(30000);
073             conn.setInstanceFollowRedirects(true);
074             InputStream is=conn.getInputStream();
075             OutputStream os = new FileOutputStream(f);
076             Utils.CopyStream(is, os);
077             os.close();
078             bitmap = decodeFile(f);
079             return bitmap;
080         } catch (Throwable ex){
081            ex.printStackTrace();
082            if(ex instanceof OutOfMemoryError)
083                memoryCache.clear();
084            return null;
085         }
086     }
087  
088     //decodes image and scales it to reduce memory consumption
089     private Bitmap decodeFile(File f){
090         try {
091             //decode image size
092             BitmapFactory.Options o = new BitmapFactory.Options();
093             o.inJustDecodeBounds = true;
094             BitmapFactory.decodeStream(new FileInputStream(f),null,o);
095              
096             //Find the correct scale value. It should be the power of 2.
097             final int REQUIRED_SIZE=70;
098             int width_tmp=o.outWidth, height_tmp=o.outHeight;
099             int scale=1;
100             while(true){
101                 if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
102                     break;
103                 width_tmp/=2;
104                 height_tmp/=2;
105                 scale*=2;
106             }
107              
108             //decode with inSampleSize
109             BitmapFactory.Options o2 = new BitmapFactory.Options();
110             o2.inSampleSize=scale;
111             return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
112         } catch (FileNotFoundException e) {}
113         return null;
114     }
115      
116     //Task for the queue
117     private class PhotoToLoad
118     {
119         public String url;
120         public ImageView imageView;
121         public PhotoToLoad(String u, ImageView i){
122             url=u;
123             imageView=i;
124         }
125     }
126      
127     class PhotosLoader implements Runnable {
128         PhotoToLoad photoToLoad;
129         PhotosLoader(PhotoToLoad photoToLoad){
130             this.photoToLoad=photoToLoad;
131         }
132          
133         @Override
134         public void run() {
135             if(imageViewReused(photoToLoad))
136                 return;
137             Bitmap bmp=getBitmap(photoToLoad.url);
138             memoryCache.put(photoToLoad.url, bmp);
139             if(imageViewReused(photoToLoad))
140                 return;
141             BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
142             Activity a=(Activity)photoToLoad.imageView.getContext();
143             a.runOnUiThread(bd);
144         }
145     }
146      
147     boolean imageViewReused(PhotoToLoad photoToLoad){
148         String tag=imageViews.get(photoToLoad.imageView);
149         if(tag==null || !tag.equals(photoToLoad.url))
150             return true;
151         return false;
152     }
153      
154     //Used to display bitmap in the UI thread
155     class BitmapDisplayer implements Runnable
156     {
157         Bitmap bitmap;
158         PhotoToLoad photoToLoad;
159         public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
160         public void run()
161         {
162             if(imageViewReused(photoToLoad))
163                 return;
164             if(bitmap!=null)
165                 photoToLoad.imageView.setImageBitmap(bitmap);
166             else
167                 photoToLoad.imageView.setImageResource(stub_id);
168         }
169     }
170  
171     public void clearCache() {
172         memoryCache.clear();
173         fileCache.clear();
174     }
175  
176 }

These are the required classes for loading image asynchronously and caching into the local memory storage.

1) MemoryCache

2) FileCache

3) Utils

MemoryCache.java PAGE TOP

view source

print?

01  package com.technotalkative.loadwebimage.imageutils;
02   
03  import java.util.Collections;
04  import java.util.Iterator;
05  import java.util.LinkedHashMap;
06  import java.util.Map;
07  import java.util.Map.Entry;
08  import android.graphics.Bitmap;
09  import android.util.Log;
10   
11  public class MemoryCache {
12   
13      private static final String TAG = "MemoryCache";
14      private Map<String, Bitmap> cache=Collections.synchronizedMap(
15              new LinkedHashMap<String, Bitmap>(10,1.5f,true));//Last argument true for LRU ordering
16      private long size=0;//current allocated size
17      private long limit=1000000;//max memory in bytes
18   
19      public MemoryCache(){
20          //use 25% of available heap size
21          setLimit(Runtime.getRuntime().maxMemory()/4);
22      }
23       
24      public void setLimit(long new_limit){
25          limit=new_limit;
26          Log.i(TAG, "MemoryCache will use up to "+limit/1024./1024.+"MB");
27      }
28   
29      public Bitmap get(String id){
30          try{
31              if(!cache.containsKey(id))
32                  return null;
33              //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78
34              return cache.get(id);
35          }catch(NullPointerException ex){
36              ex.printStackTrace();
37              return null;
38          }
39      }
40   
41      public void put(String id, Bitmap bitmap){
42          try{
43              if(cache.containsKey(id))
44                  size-=getSizeInBytes(cache.get(id));
45              cache.put(id, bitmap);
46              size+=getSizeInBytes(bitmap);
47              checkSize();
48          }catch(Throwable th){
49              th.printStackTrace();
50          }
51      }
52       
53      private void checkSize() {
54          Log.i(TAG, "cache size="+size+" length="+cache.size());
55          if(size>limit){
56              Iterator<Entry<String, Bitmap>> iter=cache.entrySet().iterator();//least recently accessed item will be the first one iterated 
57              while(iter.hasNext()){
58                  Entry<String, Bitmap> entry=iter.next();
59                  size-=getSizeInBytes(entry.getValue());
60                  iter.remove();
61                  if(size<=limit)
62                      break;
63              }
64              Log.i(TAG, "Clean cache. New size "+cache.size());
65          }
66      }
67   
68      public void clear() {
69          try{
70              //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78
71              cache.clear();
72              size=0;
73          }catch(NullPointerException ex){
74              ex.printStackTrace();
75          }
76      }
77   
78      long getSizeInBytes(Bitmap bitmap) {
79          if(bitmap==null)
80              return 0;
81          return bitmap.getRowBytes() * bitmap.getHeight();
82      }
83  }

FileCache.java PAGE TOP

Using FileCache, we will create TTImages_cache folder for caching images into it. Also to load image if synced already. We can use clear() method of FileCache class to clear synced images.

view source

print?

01  package com.technotalkative.loadwebimage.imageutils;
02   
03  import java.io.File;
04  import android.content.Context;
05   
06  public class FileCache {
07       
08      private File cacheDir;
09       
10      public FileCache(Context context){
11          //Find the dir to save cached images
12          if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
13              cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"TTImages_cache");
14          else
15              cacheDir=context.getCacheDir();
16          if(!cacheDir.exists())
17              cacheDir.mkdirs();
18      }
19       
20      public File getFile(String url){
21          //I identify images by hashcode. Not a perfect solution, good for the demo.
22          String filename=String.valueOf(url.hashCode());
23          //Another possible solution (thanks to grantland)
24          //String filename = URLEncoder.encode(url);
25          File f = new File(cacheDir, filename);
26          return f;
27           
28      }
29       
30      public void clear(){
31          File[] files=cacheDir.listFiles();
32          if(files==null)
33              return;
34          for(File f:files)
35              f.delete();
36      }
37   
38  }

Utils.java PAGE TOP

view source

print?

01  package com.technotalkative.loadwebimage.imageutils;
02   
03  import java.io.InputStream;
04  import java.io.OutputStream;
05   
06  public class Utils {
07      public static void CopyStream(InputStream is, OutputStream os)
08      {
09          final int buffer_size=1024;
10          try
11          {
12              byte[] bytes=new byte[buffer_size];
13              for(;;)
14              {
15                int count=is.read(bytes, 0, buffer_size);
16                if(count==-1)
17                    break;
18                os.write(bytes, 0, count);
19              }
20          }
21          catch(Exception ex){}
22      }
23  }

activity_main.xml PAGE TOP

view source

print?

01  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
02      xmlns:tools="http://schemas.android.com/tools"
03      android:layout_width="match_parent"
04      android:layout_height="match_parent" >
05   
06      <Button
07          android:id="@+id/btnLoadImage"
08          android:layout_width="wrap_content"
09          android:layout_height="wrap_content"
10          android:layout_centerHorizontal="true"
11          android:onClick="btnLoadImageClick"
12          android:text="Load Image" />
13   
14      <ImageView
15          android:id="@+id/imageView1"
16          android:layout_width="match_parent"
17          android:layout_height="200dp"
18          android:layout_centerInParent="true"
19          android:padding="10dp"
20          android:scaleType="fitXY"
21          android:src="@drawable/ic_launcher" />
22   
23  </RelativeLayout>

Note:

Don’t forget to include INTERNET and WRITEEXTERNALSTORAGE permission in AndroidManifest.xml

view source

print?

1   <uses-permission android:name="android.permission.INTERNET" />
2   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Download this example from here: Android – Load images from web and syncing

Reference PAGE TOP

http://www.javacodegeeks.com/2012/08/android-load-images-from-web-and-caching.html

1 Comments Leave a comment

Please login in order to leave a comment.

Newest first
  • Jojo1733 2013-10-12 16:57:43 Thread #53

    Hi am new to android.I was wondering if your codes could be customised to load images from more than one url and use a gallery to display the images.Thanks you.

  • Jojo1733 2013-10-12 16:57:43

    Hi am new to android.I was wondering if your codes could be customised to load images from more than one url and use a gallery to display the images.Thanks you.

!

Sign-in to your Chupamobile Account.

The Easiest way to Launch your next App or Game.

Join Chupamobile and get instant access to thousands of ready made App and Game Templates.

Creating an account means you’re okay with Chupamobile’s Terms of Service and Privacy Policy.