如何等待下载线程完成然后返回而不阻止UI线程?

时间:2014-08-15 10:32:07

标签: android multithreading android-asynctask android-ui

我正在尝试创建一个类来下载图像,存储它然后将其作为Drawable返回。该文件不需要多次下载,但只是第一次下载。

这是我的班级:

package com.ishan.drawabletest;
..........................
public class DrawableProvider extends ContextWrapper{

Drawable resultDrawable;

public DrawableProvider(Context base) {
    super(base);
}

public Drawable get(final String fileURL) {
    // File name that is being downloaded
    String downloadedFileName = fileURL.substring(fileURL.lastIndexOf("/")+1);
    final String imagePath = getFilesDir() + "/" + downloadedFileName;

    // Checking if the file exists or not
    final File file = new File(imagePath);
    if(file.exists()) {
        // The image already exists, have to only return it by converting into drawable
        resultDrawable = Drawable.createFromPath(imagePath);
        return resultDrawable;
    } else {
        // The image doesn't exists already.
        Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    // Downloading the image here
                    ..................
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                resultDrawable = Drawable.createFromPath(imagePath);
            }
        };
        t.start();
        // Waiting for the thread to finish before returning using join
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return resultDrawable;
    }
}
}

这个类被调用并像这样使用。 :

ImageView permanentImageView = (ImageView) findViewById(R.id.permaImageView);
    DrawableProvider dp = new DrawableProvider(this);
    permanentImageView.setImageDrawable(dp.get("http://youthvibe2014server.herokuapp.com/public/selenaGomez.jpg"));

对于图像已经可用的情况,它可以正常工作。问题是,如果我不等待(即,如果删除了连接)线程完成并立即返回,则屏幕不包含图像甚至不是默认图像(以XML定义)哪个应该在那里,直到下载完成。

看起来像这样。

The screen without the image or even without the default image.

我想是这样的,因为我的get方法没有等待线程完成并返回null,因此permanentImageView包含null。< / p>

但是如果我等待让线程完成。屏幕最终显示下载的图像,但暂时它变为空白,看起来像这样。 :

The blank screen when waiting for thread to finish

我想这是因为当我等待线程完成时,我的UI线程暂时被阻止。

我无法使用AsyncTask,因为我正在扩展ContextWrapper,因此无法扩展AsyncTask。有没有办法等待我的线程完成然后返回而不阻塞我的UI线程?

2 个答案:

答案 0 :(得分:1)

  

我无法使用AsyncTask,因为我正在扩展ContextWrapper,因此无法扩展AsyncTask。

所以,摆脱ContextWrapper。无论如何,您并未将其用于预期目的。继承它并没有对你做任何有用的事情,所以继承自AsyncTask

或者,更好的是,使用任何一个看似无限数量的现有库来完成这项工作。

答案 1 :(得分:0)

一种可能的解决方案:将活动发送到您的班级并使用

activity.RunOnUiThread(Runnable runnable)

在runnable中,您可以像回调一样通知用户。 你可以从后台线程中调用这个函数。

RunOnUiThread API Document

下载图像后

resultDrawable = Drawable.createFromPath(imagePath); 

放置RunOnUIThread并创建对Fragment / Activity的回调。此回调从UI中获取Image已准备就绪,因此您可以将其放在ImageView中。

例如创建一个名为

的函数
public Drawable getDrawable() {
      return resultDrawable;

}
回调中的

使用此函数将Image放在ImageView中。