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()方法中将文件
传递给您。