0

Hi can any body suggest me the class which is helpful for loading large no of images which also handle cache and disc cache

i have used ImageLoder class but it is not efficient for loading all images and i am getting VMEXCEED error

my class is below

     public class ImageLoader1 {

String Url1;
// the simplest in-memory cache implementation. This should be replaced with
// something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
public HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();

private File cacheDir;

public ImageLoader1(Context context, String Url) {
    // Make the background thead low priority. This way it will not affect
    // the UI performance
    photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
    Url1 = Url;
    // Find the dir to save cached images
    if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
        cacheDir = new File(android.os.Environment.getExternalStorageDirectory(), "LazyList");
    else
        cacheDir = context.getCacheDir();
    if (!cacheDir.exists())
        cacheDir.mkdirs();
}

final int stub_id = R.drawable.placeholder;

// ----Method for Displaying image
public void DisplayImage(String url, Activity activity, ImageView imageView) {
    if (cache.containsKey(url)) {
        // ---Sets a Bitmap as the content of this ImageView.
        imageView.setImageBitmap(cache.get(url));
    } else {
        queuePhoto(url, activity, imageView);
        // imageView.setImageResource(stub_id);
    }
}

public void DisplayImage1(String url, ImageView imageView) {
    if (cache.containsKey(url))
        // ---Sets a Bitmap as the content of this ImageView.
        imageView.setImageBitmap(cache.get(url));
    else {
        queuePhoto1(url, imageView);
        // imageView.setImageResource(stub_id);
    }
}

private void queuePhoto(String url, Activity activity, ImageView imageView) {
    // This ImageView may be used for other images before. So there may be
    // some old tasks in the queue. We need to discard them.
    photosQueue.Clean(imageView);
    PhotoToLoad p = new PhotoToLoad(url, imageView);
    synchronized (photosQueue.photosToLoad) {
        photosQueue.photosToLoad.push(p);
        photosQueue.photosToLoad.notifyAll();
    }

    // start thread if it's not started yet
    if (photoLoaderThread.getState() == Thread.State.NEW)
        photoLoaderThread.start();
}

private void queuePhoto1(String url, ImageView imageView) {
    // This ImageView may be used for other images before. So there may be
    // some old tasks in the queue. We need to discard them.
    photosQueue.Clean(imageView);
    PhotoToLoad p = new PhotoToLoad(url, imageView);
    synchronized (photosQueue.photosToLoad) {
        photosQueue.photosToLoad.push(p);
        photosQueue.photosToLoad.notifyAll();
    }

    // start thread if it's not started yet
    if (photoLoaderThread.getState() == Thread.State.NEW)
        photoLoaderThread.start();
}

private Bitmap getBitmap(String url) {
    // I identify images by hashcode. Not a perfect solution, good for the
    // demo.
    String filename = String.valueOf(url.hashCode());
    File f = new File(cacheDir, filename);

    // from SD cache
    Bitmap b = decodeFile(f);
    if (b != null)
        return b;

    // from web
    try {
        Bitmap bitmap = null;
        InputStream is = new URL(url).openStream();
        OutputStream os = new FileOutputStream(f);
        Utils.CopyStream(is, os);
        os.close();
        bitmap = decodeFile(f);
        return bitmap;
    } catch (Exception ex) {
        ex.printStackTrace();
        return null;
    }
}

// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
    try {
        // decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f), null, o);

        // Find the correct scale value. It should be the power of 2.
        final int REQUIRED_SIZE = 50;
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
                break;
            width_tmp /= 2;
            height_tmp /= 2;
            scale++;
        }

        // decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {
    }
    return null;
}

// Task for the queue
private class PhotoToLoad {
    public String url;
    public ImageView imageView;

    public PhotoToLoad(String u, ImageView i) {
        url = u;
        imageView = i;
    }
}

PhotosQueue photosQueue = new PhotosQueue();

// ---Method for stopping thread
public void stopThread() {
    photoLoaderThread.interrupt();
}

// stores list of photos to download
class PhotosQueue {
    private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();

    // removes all instances of this ImageView
    public void Clean(ImageView image) {
        for (int j = 0; j < photosToLoad.size();) {
            if (photosToLoad.get(j).imageView == image)
                photosToLoad.remove(j);
            else
                ++j;
        }
    }
}

// ----class for photoLoading
class PhotosLoader extends Thread {
    public void run() {
        try {
            while (true) {
                // thread waits until there are any images to load in the
                // queue
                if (photosQueue.photosToLoad.size() == 0)
                    synchronized (photosQueue.photosToLoad) {
                        photosQueue.photosToLoad.wait();
                    }
                if (photosQueue.photosToLoad.size() != 0) {
                    PhotoToLoad photoToLoad;
                    synchronized (photosQueue.photosToLoad) {
                        photoToLoad = photosQueue.photosToLoad.pop();
                    }
                    Bitmap bmp = getBitmap(photoToLoad.url);
                    cache.put(photoToLoad.url, bmp);
                    if (((String) photoToLoad.imageView.getTag()).equals(photoToLoad.url)) {
                        BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad.imageView);
                        Activity a = (Activity) photoToLoad.imageView.getContext();
                        a.runOnUiThread(bd);
                    }
                }
                if (Thread.interrupted())
                    break;
            }
        } catch (InterruptedException e) {
            // allow thread to exit
        }
    }
}

PhotosLoader photoLoaderThread = new PhotosLoader();

// Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable {
    Bitmap bitmap;
    ImageView imageView;

    public BitmapDisplayer(Bitmap b, ImageView i) {
        bitmap = b;
        imageView = i;
    }

    public void run() {
        if (bitmap != null)
            imageView.setImageBitmap(bitmap);
        // else
        // imageView.setImageResource(stub_id);
    }
}

public void clearCache() {
    // clear memory cache
    cache.clear();

    // clear SD cache
    File[] files = cacheDir.listFiles();
    for (File f : files)
        f.delete();
}

}

Siddhpura Amit
  • 14,534
  • 16
  • 91
  • 150

2 Answers2

3

you can use Android-Universal-Image-Loader to load large amount images.

[ADDITION 1]

Look at the below example project, it gets contact's images and load to listview. It will give you an idea about usage of universal image laoder.

https://dl.dropbox.com/u/68130108/UniversalImageLoaderExample.rar

Talha
  • 12,673
  • 5
  • 49
  • 68
  • i have used this code but it seems complected it uses Fragment and i don't have any fragment :* – Siddhpura Amit Dec 21 '12 at 13:41
  • You can use this for listview, gridview also – Talha Dec 21 '12 at 13:43
  • @SiddhpuraAmit: you do not need to use fragment there. Just add `jar` in your project and `initalize() ImageLoader` and ya.. its works I have used in many projects. @talhakosen +1 – MAC Dec 21 '12 at 13:48
  • @SiddhpuraAmit pls look at the example you will understand how you can use it – Talha Dec 21 '12 at 13:54
  • Hello Talhakosen i have used imageloader as you suggested but when i tried it again this activity the images will taking so much time to load :( – Siddhpura Amit Dec 29 '12 at 12:38
1

As talhakosen told use Universal Image Loader.

Just download its JAR file add into your libs folder create instance of ImageLoader

for example:

ImageLoader imgLoader = ImageLoader.getInstance();
imgLoader.displayImage(url,imageView);
MAC
  • 15,799
  • 8
  • 54
  • 95