0

嗨,任何人都可以向我推荐一个有助于加载大量图像的类,这些图像还可以处理缓存和磁盘缓存

我使用了 ImageLoder 类,但加载所有图像效率不高,我收到VMEXCEED 错误

我的课在下面

     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();
}

}

4

2 回答 2

3

您可以使用Android-Universal-Image-Loader加载大量图像。

[补充1]

看下面的示例项目,它获取联系人的图像并加载到列表视图。它将让您了解通用图像加载器的用法。

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

于 2012-12-21T13:36:44.957 回答
1

正如 talhakosen 所说,使用Universal Image Loader

只需下载它的JAR文件添加到您的libs文件夹中创建实例ImageLoader

例如:

ImageLoader imgLoader = ImageLoader.getInstance();
imgLoader.displayImage(url,imageView);
于 2012-12-21T13:54:49.130 回答