在Java中,我已经习惯了 Futures
。现在我正在看Android,和 AsyncTask
实现几乎所有相同的方法并涵盖类似的生命周期。但是,如果我想要保持一致并在我的代码中使用Future,我必须将AsyncTask包装在一个愚蠢的包装器中,因为它实际上并没有实现Future。
他们需要添加的只是一个 isDone()
方法,这似乎是微不足道的,然后添加 implements Future<Result>
。 (稍后补充:请参阅下面的答案,了解它会有多么微不足道)。
任何Android专家都知道一些很好的理由/模糊的错误,它可能导致为什么没有这样做?
我仍然对“为什么”不使用AsyncTask进行未来的理论原因感兴趣。
但是,为了记录,我最终创建了自己的小班(如下所示)。如果你想要一个Future,只需扩展它而不是AsyncTask。 IMO,比@Eng.Fouad在代码中访问私有mFuture的想法更清晰。 (但是感谢这个想法,它让我看了一下源代码!)YMMV。
public abstract class FutureAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> implements Future<Result>{
@Override
public boolean isDone() {
return AsyncTask.Status.FINISHED == getStatus();
}
}
从阅读实际代码 AsyncTask.java
它实际上 使用 一个 Future
任务,然后更多。一个 Future
是一个在旅途中异步执行的任务。一个 AsyncTask
计划在一个(或池)后台线程的队列上。
一个 AsyncTask
实际上比a更“优越” Future
任务。它确实进行了奇特的调度和优化 Future
的功能。只需看看API介绍级别。 Future
是从API 1.0开始引入的。该 AsyncTask
对象是在API 3中引入的。
AsyncTask有一个Future任务,而不是Future。
AsyncTask.java
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
AsyncTask
太简单了。它适用于可能需要几秒钟的短任务,但您不想锁定UI线程。如果你真的需要一个 Future
,你的任务可能太复杂了 AsyncTask
无论如何。
你可以检查一下的状态 AsyncTask
通过电话 getStatus()
。这将返回一个可以是其中之一的枚举 Status.PENDING
, Status.RUNNING
要么 Status.FINISHED
。