从MediaStore图像异步下载到GridView控件 [英] Async download of images to gridview from MediaStore

查看:163
本文介绍了从MediaStore图像异步下载到GridView控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有大约1500图像的GridView控件。我使用的是从MediaStore缩略图显示它们。但是,当我在填充UI线程网格,它的工作速度太慢,第一次(缩略图尚未创建?)。所以,我决定这个过程转移到后台。使用此教程并相互我写这类:

I have a gridview of about 1500 images. I'm using thumbnails from MediaStore to show them. But when I've populated the grid in UI thread it worked too slow for the first time (thumbnails not created yet?). So I've decided to move this process to background. Using this tutorial and one another I've written this class:

public class ImageLoader {
// -----------------------------------------------------------------------
//
// Fields
//
// -----------------------------------------------------------------------
private static Context mContext;
private static ImageLoader mImageLoader = new ImageLoader();
// -----------------------------------------------------------------------
//
// Static methods
//
// -----------------------------------------------------------------------
public static void init(Application application){
    mContext = application;
}

public static ImageLoader getInstance(){
    return mImageLoader;
}

// -----------------------------------------------------------------------
//
// Methods
//
// -----------------------------------------------------------------------
public void download(ImageView imageView, final long id) {
    Boolean b = cancelPotentialDownload(id, imageView);
    Log.v("Loader", "download " + b.toString());
    if (b) {
        DownloadImageTask task = new DownloadImageTask(imageView, id);
        DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
        imageView.setImageDrawable(downloadedDrawable);
        task.execute();
    }
}

// -----------------------------------------------------------------------
//
// Inner classes
//
// -----------------------------------------------------------------------
private class DownloadImageTask extends AsyncTask<Void, Void, Bitmap>{
    private final WeakReference<ImageView> iv;
    private final long id;

    public DownloadImageTask(ImageView imageView, long id){
        iv = new WeakReference<ImageView>(imageView);
        this.id = id;
    }

    @Override
    protected Bitmap doInBackground(Void... params) {
        Bitmap bitmap = downloadImageThumbnail(id);
        return bitmap;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
         Log.v("Task", "completed " + (result == null)); 
         if (iv != null) {
                ImageView imageView = iv.get();
                DownloadImageTask bitmapDownloaderTask = getDownloadImageTask(imageView);
                // Change bitmap only if this process is still associated with it
                if (this == bitmapDownloaderTask) {
                    imageView.setImageBitmap(result);
                }
            }
    }
}

static class DownloadedDrawable extends ColorDrawable {
    private final WeakReference<DownloadImageTask> downloadImageTaskReference;

    public DownloadedDrawable(DownloadImageTask downloadImageTask) {
        super(Color.TRANSPARENT);
        downloadImageTaskReference = new WeakReference<DownloadImageTask>(downloadImageTask);
    }

    public DownloadImageTask getDownloadImageTask() {
        return downloadImageTaskReference.get();
    }
}

// -----------------------------------------------------------------------
//
// Private static helper methods
//
// -----------------------------------------------------------------------
private static boolean cancelPotentialDownload(long id, ImageView imageView) {
    DownloadImageTask downloadImageTask = getDownloadImageTask(imageView);

    if (downloadImageTask != null) {
        long imageId = downloadImageTask.id;
        if ((imageId == 0) || (imageId != id)) {
            Boolean b = downloadImageTask.cancel(true);
            Log.v("Task", "Stopped " + b.toString());
        } else {
            // The same URL is already being downloaded.
            return false;
        }
    }
    return true;
}

private static DownloadImageTask getDownloadImageTask(ImageView imageView) {
    if (imageView != null) {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof DownloadedDrawable) {
            DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
            return downloadedDrawable.getDownloadImageTask();
        }
    }
    return null;
}
// -----------------------------------------------------------------------
//
// Private helper methods
//
// -----------------------------------------------------------------------
private Bitmap downloadImageThumbnail(long id) {
    Bitmap bitmap = MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(), id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
    return bitmap;
}

}

但是,有一个问题,这么大数量的图像 - 有很多在同一时间运行的任务打完活动开始还有一个空的GridView,然后突然就变得与图像(我读过的AsyncTask填写来源和不理解为什么是这样工作的 - 只有一个在同一时间运行的任务)。而另一个 - 如果你速度快向下滚动列表视图大图像(1500),那么你就需要等待太长时间看到的结果。无论如何,我需要做的GridView顺利填充。所以我决定来管理自己的任务,并提出了一些修改:

But there was an issue with such a big number of images - there was a lot of tasks running at the same time so after activity starts there is a blank gridview and then suddenly it becomes filled with images (I've read AsyncTask sources and didn't understand why it works this way - there is only one task running at the same time). And another one - if you fastly scroll down a large listview of images (1500) then you'll need to wait too long to see the result. Anyway I need to make gridview populated smoothly. So I've decided to manage tasks myself and made some modifications:

private static final int POOL_CAPACITY = 10;
// -----------------------------------------------------------------------
//
// Fields
//
// -----------------------------------------------------------------------
private static Context mContext;
private static ImageLoader mImageLoader = new ImageLoader();


private static ArrayList<DownloadImageTask> executingPool = new ArrayList<ImageLoader.DownloadImageTask>();
private static ArrayList<DownloadImageTask> waitingPool = new ArrayList<ImageLoader.DownloadImageTask>();
// -----------------------------------------------------------------------
//
// Static methods
//
// -----------------------------------------------------------------------
public static void init(Application application){
    mContext = application;
}

public static ImageLoader getInstance(){
    return mImageLoader;
}

// -----------------------------------------------------------------------
//
// Methods
//
// -----------------------------------------------------------------------
public void download(ImageView imageView, final long id) {
    Boolean b = cancelPotentialDownload(id, imageView);
    Log.v("Loader", "download " + b.toString());
    if (b) {
        DownloadImageTask task = new DownloadImageTask(imageView, id);
        Log.v("Loader","download " + task.hashCode() + " ex size " + executingPool.size() + " wa size " + waitingPool.size());
        DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
        imageView.setImageDrawable(downloadedDrawable);
        addTask(task);
    }
}

private void addTask(DownloadImageTask task){
    Log.v("Loader", "addTask " + task.hashCode() + " ex size " + executingPool.size() + " wa size " + waitingPool.size());
    if(executingPool.size() < POOL_CAPACITY) {
        executingPool.add(task);
        task.execute();
    }
    else
        waitingPool.add(task);
}

private synchronized void executeNext(DownloadImageTask finished){
    Log.v("Loader", "executeNext " + finished.hashCode() + " ex size " + executingPool.size() + " wa size " + waitingPool.size());
    executingPool.remove(finished);
    if(waitingPool.size() > 0){
        DownloadImageTask task = waitingPool.remove(0);
        addTask(task);
    }
}
// -----------------------------------------------------------------------
//
// Inner classes
//
// -----------------------------------------------------------------------
private class DownloadImageTask extends AsyncTask<Void, Void, Bitmap>{
    private final WeakReference<ImageView> iv;
    private final long id;

    public DownloadImageTask(ImageView imageView, long id){
        iv = new WeakReference<ImageView>(imageView);
        this.id = id;
    }

    @Override
    protected Bitmap doInBackground(Void... params) {
        Log.v("Loader", "doInBackground " + this.hashCode() + " ex size " + executingPool.size() + " wa size " + waitingPool.size());
        Bitmap bitmap = downloadImageThumbnail(id);
        return bitmap;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
         Log.v("Task", "completed " + (result == null)); 
         if (iv != null) {
                ImageView imageView = iv.get();
                DownloadImageTask bitmapDownloaderTask = getDownloadImageTask(imageView);
                // Change bitmap only if this process is still associated with it
                if (this == bitmapDownloaderTask) {
                    imageView.setImageBitmap(result);
                }
            }
         executeNext(this);
    }
}

static class DownloadedDrawable extends ColorDrawable {
    private final WeakReference<DownloadImageTask> downloadImageTaskReference;

    public DownloadedDrawable(DownloadImageTask downloadImageTask) {
        super(Color.TRANSPARENT);
        downloadImageTaskReference = new WeakReference<DownloadImageTask>(downloadImageTask);
    }

    public DownloadImageTask getDownloadImageTask() {
        return downloadImageTaskReference.get();
    }
}

// -----------------------------------------------------------------------
//
// Private static helper methods
//
// -----------------------------------------------------------------------
private static boolean cancelPotentialDownload(long id, ImageView imageView) {
    DownloadImageTask downloadImageTask = getDownloadImageTask(imageView);

    if (downloadImageTask != null) {
        long imageId = downloadImageTask.id;
        if ((imageId == 0) || (imageId != id)) {
            Boolean b = downloadImageTask.cancel(true);
            Log.v("Task", "Stopped " + b.toString());
        } else {
            // The same URL is already being downloaded.
            return false;
        }
    }
    return true;
}

private static DownloadImageTask getDownloadImageTask(ImageView imageView) {
    if (imageView != null) {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof DownloadedDrawable) {
            DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
            return downloadedDrawable.getDownloadImageTask();
        }
    }
    return null;
}
// -----------------------------------------------------------------------
//
// Private helper methods
//
// -----------------------------------------------------------------------
private Bitmap downloadImageThumbnail(long id) {
    Bitmap bitmap = MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(), id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
    return bitmap;
}

}

现在GridView的填充速度较快,但仍有快速向下滚动的问题。而另一个 - 有时我得到一个错误:

Now gridview populated faster but there is still an issue with fast scrolling down. And another one - sometimes I get an error:

java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)

我真的不知道该怎么办。我试图让addTask和executeNext同步(我不擅长有关同步的问题),但它的工作原理,甚至值得。我不知道任何第三方库,有助于下载图像的缩略图被它的ID从mediastore。也许你能帮助我吗?

I really don't know what to do. I've tried to make addTask and executeNext synchronized (I'm not good at questions about synchronization) but it works even worth. I don't know any third party library which helps to download image thumbnail by it's id from mediastore. Maybe you can help me?

推荐答案

非常感谢给<一个href=\"http://$c$chenge.net/blog/2011/06/android-development-tutorial-asynchronous-lazy-loading-and-caching-of-listview-images/\"相对=nofollow>这个的例子。我已经修改了它一点点地使用来自MediaStore和LruCache大拇指。现在它的工作原理pretty不错。

Thanks a lot to this example. I've modified it a little bit to use thumbs from MediaStore and LruCache. It works pretty good now.

这篇关于从MediaStore图像异步下载到GridView控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆