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

Android 如何等待下载线程完成,然后返回而不阻塞UI线程?,android,multithreading,android-asynctask,android-ui,Android,Multithreading,Android Asynctask,Android Ui,我正在尝试创建一个类来下载图像,存储它,然后将其作为可绘制的返回。文件不需要下载多次,只需要第一次 这是我的班级: package com.ishan.drawabletest; .......................... public class DrawableProvider extends ContextWrapper{ Drawable resultDrawable; public DrawableProvider(Context base) { super(ba

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

这是我的班级:

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"));
它适用于图像已经可用的情况。问题是,如果I不等待线程立即完成并返回(即,如果删除了连接),那么屏幕上就不包含图像,甚至不包含默认图像(用XML定义),直到下载完成为止,默认图像都应该在那里

看起来像这样

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

但是如果我会等待线程完成。屏幕最终显示下载的图像,但暂时为空,如下所示:

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

我猜这是因为当我等待线程完成时,我的UI线程暂时被阻塞了


我不能使用
AsyncTask
,因为我正在扩展
ContextWrapper
,因此也不能扩展
AsyncTask
。有没有一种方法可以等待我的线程完成,然后返回而不阻塞我的UI线程?

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

activity.RunOnUiThread(Runnable runnable)
在runnable中,您可以像回调一样通知用户。 您可以从后台线程调用此函数

下载图像后

resultDrawable = Drawable.createFromPath(imagePath); 
将RunOnUIThread和create回调放入片段/活动。此回调通知UI图像已准备就绪,以便您可以将其放置在ImageView中

例如,创建一个调用

public Drawable getDrawable() {
      return resultDrawable;

}
在回调本身中,使用此函数将图像放置在ImageView中

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

所以,去掉
ContextWrapper
。无论如何,您并没有将其用于预期目的。从它继承对您没有任何用处,因此从
AsyncTask
继承


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

您是否建议下载的代码应该在UI线程上运行?请更新答案。我想这有点不清楚遵循@commonware建议并使用异步任务。尤其是b/c,它对刚刚学习的人更友好。至于为什么在不等待(t.join)时默认图像不显示,这是因为在设置图像之前函数返回时,您返回了null,我确信您会继续使用所述null来清空默认图像。如果我没有使用
ContextWrapper
,我如何使用
getFilesDir()
,因为当我扩展
AsyncTask
时,
getFilesDir()
似乎没有定义?@Ishan:
getFilesDir()
Context
上的一个方法,例如
this
您正在传递到
DrawableProvider
类中的方法
getFilesDir()
返回一个
文件
。将
文件
传递到
异步任务的构造函数中
。或者,如果愿意,将
文件
对象传递给
AsyncTask
实例上的
execute()
,它将在
doInBackground()方法中将
文件
传递给您。